<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.sandbox.joomla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Javiparati</id>
	<title>Joomla! Documentation - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.sandbox.joomla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Javiparati"/>
	<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/Special:Contributions/Javiparati"/>
	<updated>2026-06-11T01:39:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Joomla_info_page/es-ES&amp;diff=329837</id>
		<title>Joomla info page/es-ES</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Joomla_info_page/es-ES&amp;diff=329837"/>
		<updated>2016-08-26T07:47:31Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* ¿Cómo puedes apoyar a Joomla!? */ Updated links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Spanish =&lt;br /&gt;
&lt;br /&gt;
== ¿Qué es Joomla? ==&lt;br /&gt;
Joomla es un premiado sistema de Gestión de Contenidos (CMS), que permite crear sitios Web y poderosas aplicaciones online. Muchos aspectos, incluyendo su fácil uso y extensibilidad han convertido a Joomla! en el software para Web más popular. Y lo mejor de todo, Joomla es Software Libre disponible gratuitamente para todo el mundo. Entre los beneficios de Joomla se incluye:&lt;br /&gt;
&lt;br /&gt;
* Fácil instalación&lt;br /&gt;
* Simple mantenimiento del web&lt;br /&gt;
* Seguridad y estabilidad&lt;br /&gt;
* Potentes extensiones comerciales y gratuitas&lt;br /&gt;
* Una enorme cantidad de plantillas para cambiar fácilmente el look de tu web.&lt;br /&gt;
&lt;br /&gt;
Tienes más información sobre Joomla! en español [http://docs.joomla.org/Joomla_brochure/es-ES en este otro artículo de la documentación].&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir Joomla? ==&lt;br /&gt;
* Descarga Joomla! desde los [http://www.joomla.org/download.html repositorios oficiales].&lt;br /&gt;
* Descarga los paquetes de idioma español de los [http://community.joomla.org/translations.html grupos de traducción acreditados] desde aquí: &lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=30 Paquetes de la rama 1.5.x]&lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation1_6/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=5597 Paquetes de la rama 2.5.x]&lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation3_x/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=6445 Paquetes de la rama 3.0.x]&lt;br /&gt;
* Otras traducciones&lt;br /&gt;
** [http://joomlacode.org/gf/project/spanishlanguage/frs/ Traducciones más antiguas del grupo acreditado anterior (incluye traducciones de la rama 1.0.x)]&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde descargar extensiones? ==&lt;br /&gt;
* Descarga extensiones en: http://extensions.joomla.org/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir documentación para Joomla? ==&lt;br /&gt;
* Documentación en inglés: http://docs.joomla.org/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir soporte/ayuda para Joomla? ==&lt;br /&gt;
* Soporte gratuito en Inglés: http://forum.joomla.org/&lt;br /&gt;
* Soporte gratuito en Español: &lt;br /&gt;
** http://forum.joomla.org/viewforum.php?f=24&lt;br /&gt;
** http://magazine.joomla.org/international-stories-all/articles-in-spanish-all&lt;br /&gt;
* Soporte gratuito en lugares no oficiales:&lt;br /&gt;
** http://foro.comunidadjoomla.org&lt;br /&gt;
* Soporte comercial: http://resources.joomla.org/ (website en Inglés)&lt;br /&gt;
&lt;br /&gt;
== Eventos regionales / Joomladays ==&lt;br /&gt;
Las comunidades locales organizan eventos Joomla! conocidos como &#039;&#039;Joomla!Days&#039;&#039; por todo el mundo. Un Joomla Day es un evento creado exclusivamente para los usuarios de Joomla! y sus proyectos relacionados. Habitualmente tienen una audiencia regional. Más información en: http://events.joomla.org/joomla-days.html&lt;br /&gt;
&lt;br /&gt;
== Joomla User Groups (JUG) ==&lt;br /&gt;
Los Grupos de usuarios de Joomla (JUG) son una manera magnífica de conocer gente, conseguir ayuda para un proyecto, o compartir las experiencias con otros usuarios de Joomla. Joomla! está en todos los lugares del mundo así que revisa si ya existe algún JUG en tu zona. En caso contrario, ¿Por qué no creas uno?&lt;br /&gt;
&lt;br /&gt;
* JUGs en Centro América: http://community.joomla.org/user-groups/central-america.html&lt;br /&gt;
* JUGs en el Caribe: http://community.joomla.org/user-groups/caribbean.html&lt;br /&gt;
* JUGs en Sud América: http://community.joomla.org/user-groups/south-america.html&lt;br /&gt;
* JUGs España: http://community.joomla.org/user-groups/europe/spain.html&lt;br /&gt;
&lt;br /&gt;
* Preguntas frecuentes JUG: http://community.joomla.org/jug-faq-spanish.html&lt;br /&gt;
&lt;br /&gt;
== ¿Cómo puedes apoyar a Joomla!? ==&lt;br /&gt;
* Responde dudas de otras personas en los foros http://forum.joomla.org/viewforum.php?f=24&amp;amp;sid=cf489f4ab48512121a5de9da481fba9f&lt;br /&gt;
* Escribe o traduce un tutorial o documentación https://docs.joomla.org/JDOC:How_to_Contribute_to_Joomla!_Documentation/es&lt;br /&gt;
* Desarrolla una Extensión o una plantilla de diseño https://docs.joomla.org/Portal:Developers/es&lt;br /&gt;
* Testea y comunica los errores que encuentres https://docs.joomla.org/Filing_bugs_and_issues/es&lt;br /&gt;
* Únete a un equipo de trabajo Joomla! https://volunteers.joomla.org/working-groups&lt;br /&gt;
* Colabora en la organización y participa en los eventos Joomla! https://events.joomla.org/&lt;br /&gt;
* Apoya económicamente o de otras maneras: http://contribute.joomla.org/&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Code_sprints&amp;diff=305425</id>
		<title>Code sprints</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Code_sprints&amp;diff=305425"/>
		<updated>2016-05-25T07:16:33Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&amp;lt;languages /&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
A code sprint is a dedicated session in which a group of volunteers come together at a geographic location to work on code for the Joomla project. Examples of code sprint sessions could include UI/UX improvements, working on new features, or long term planning and architecture work. Typically, six to ten experienced individuals will be brought together for two days for these events. If you wish to form your own sprint then read the [[S:MyLanguage/Joomla:Sprint_Policy|policy]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
The code sprints are organised by the Joomla community together with the Production Leadership Team. These events are supported by the OpenSourceMatters and other sponsors.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
Code Sprints in 2013:&lt;br /&gt;
* &#039;&#039;&#039;Rapid Application Development Code Sprint&#039;&#039;&#039;, July 2013, Pistoia, Italy&lt;br /&gt;
* &#039;&#039;&#039;Code stability and bug triage Code Sprint&#039;&#039;&#039;, Aug 2013, Nashville, Tennessee, USA. More info:&lt;br /&gt;
&amp;lt;/translate&amp;gt; http://community.joomla.org/blogs/leadership/1757-call-for-participants-for-code-sprint.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Code Sprints in 2014:&lt;br /&gt;
* &#039;&#039;&#039;Architecture Sprint&#039;&#039;&#039;, Feb 8-9, San Jose, California, USA.&lt;br /&gt;
* &#039;&#039;&#039;JUX Sprint&#039;&#039;&#039;, July 8-9, More info: http://developer.joomla.org/cms/user-experience/610-jux-code-sprint-report.html&lt;br /&gt;
* &#039;&#039;&#039;Bug Clean Up Sprint&#039;&#039;&#039;, July 26-27, More info: http://magazine.joomla.org/issues/issue-aug-2014/item/2228-joomla-bug-sprint-in-manchester&lt;br /&gt;
* &#039;&#039;&#039;Code Style Code Sprint&#039;&#039;&#039;, Oct 11-12, Madrid, Spain.  More info at: http://magazine.joomla.org/issues/issue-nov-2014/item/2353-two-joomla-code-sprints&lt;br /&gt;
* &#039;&#039;&#039;Code Testing Code Sprint&#039;&#039;&#039;, Oct 14, Montabaur, Germany. More info at: http://thephp.cc/viewpoints/blog/2014/10/joomla-phpunit-code-sprint&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Code Sprints in 2015:&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Joomla 4 Architecture Sprint&#039;&#039;&#039;, July 10-12, Odense, Denmark. More info at: http://volunteers.joomla.org/reports/115-joomla-4-architecture-sprint-odense-dk&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Joomla 4 UX and Architecture Sprint&#039;&#039;&#039;, October 10-12, Athens, Greece.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Joomla! Automated Testing Code Sprint&#039;&#039;&#039;, October 28th - November 2nd, Karlsruhe, Germany. More info at: https://magazine.joomla.org/issues/issue-december-2015/item/2912-the-joomla-automated-testing-code-sprint-2015&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
[[Category:Events]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=GSOC_2016_Project_Ideas&amp;diff=279016</id>
		<title>GSOC 2016 Project Ideas</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=GSOC_2016_Project_Ideas&amp;diff=279016"/>
		<updated>2016-03-02T12:39:44Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Project VIII: Browser Automated Tests for Joomla! CMS (covering Users and Content features) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to GSoC 2016 Ideas Page ==&lt;br /&gt;
Welcome to the [[GSOC_2016|Joomla! Google Summer of Code (GSoC) 2016 project]] ideas page. As we move forward with the 2016 version of the Joomla! GSoC, we will post ideas that have been submitted to the GSoC Team below.&lt;br /&gt;
&lt;br /&gt;
Please keep in mind that projects need to be realistically something that is able to be functionally completed by a student working full time for about eight weeks. Thanks!&lt;br /&gt;
&lt;br /&gt;
If you are interested in participating as a student please review the materials on applying that are available at [http://www.google-melange.com/gsoc/document/show/gsoc_program/google/gsoc2015/help_page Google].  We strongly encourage you to ask questions about process and ideas on our [https://groups.google.com/forum/#!forum/jgsoc-2016 joomla-gsoc mailing list].&lt;br /&gt;
&lt;br /&gt;
Guidelines for sending proposal are present on our [https://docs.joomla.org/GSOC_2016 GSoC Home Page]&lt;br /&gt;
&lt;br /&gt;
Find examples of other years at https://docs.joomla.org/GSOC_2014_Project_Ideas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--== Important Guidelines on Submitting Ideas ==&lt;br /&gt;
&lt;br /&gt;
You do not have to be a GSoC student or mentor to suggest possible project ideas.&lt;br /&gt;
If you have ideas for the Joomla Google Summer of Code Program please send them to us at this form: &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
::&#039;&#039;&#039;[https://docs.google.com/forms/d/1VfQwcEq-apsHqpPRYjwPKzN5R5zNLmbJKa5Wfpp7oQI/viewform?c=0&amp;amp;w=1 Click for Ideas Submit Form]&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are some important guidelines to submit ideas, please read these carefully before adding your ideas:&lt;br /&gt;
* Ensure your idea is able to be completed in a fixed period of time. GSoC runs officially &#039;&#039;&#039;between May 23th 2016 and August 30th 2016.&#039;&#039;&#039; This is a very short period of actual coding time. Ideas should respect the time that students have available for the program. &lt;br /&gt;
* Keep ideas realistic. The ideas on this list should maintain a realistic amount of work for a single student, junior level-developer, who is working with a compressed timeline and a fixed completion (&#039;pencils down&#039;) date. &lt;br /&gt;
* Keep ideas core. The purpose of GSoC is to improve Joomla itself. This is not the time to add ideas for new extensions or features that may not be included by the PLT. If the idea is related to the framework, please consult the framework team directly about new ideas to ensure there is interest in having the package included as an official Joomla Framework package. &lt;br /&gt;
* Joomla 4. Ideas centered around Joomla 4 would not fit in well with the goal of GSoC 2016, we would recommend to discuss the idea on our mailing lists before suggesting.&lt;br /&gt;
* When in doubt, reach out. If you&#039;re unsure if your idea belongs on this list, please post to the GSoC 2016 mailing list and ask about the community&#039;s interest. &lt;br /&gt;
* No documentation-focused projects. Google Summer of &#039;&#039;Code&#039;&#039; is a program about code. We expect our students to document their work, but writing documentation for Joomla as a project does not align with the goals of GSoC. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|250px|center|link=GSOC 2016]]&lt;br /&gt;
== Idea Pool ==&lt;br /&gt;
&lt;br /&gt;
=== Joomla CMS Ideas ===&lt;br /&gt;
&lt;br /&gt;
====Project I: Improved multi-lingual content management ====&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Project Description:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;The idea is that when users want to translate content items on a multi-language site, they can have the articles side-by-side (dual-pane). This way you don&#039;t have to switch back and forth between articles. Respect also the ACL settings. So someone assigned for Dutch cannot translate any French documents for example.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;A dual-pane translation screen&amp;lt;br&amp;gt;An ACL setting for allowing access to language based articles&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, Joomla CMS multi-lingual system, JavaScript, Joomla ACL&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to Hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:rob@pollen-8.co.uk Rob Clayburn],[mailto:jean-marie.simonet@community.joomla.org Jean-Marie Simonet]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project II: Shareable Draft Content ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;There is currently no easy way to share a draft version of an unpublished article with people who do not have Administrator access.  This project would add elements to the Articles: Edit user interface that would support the generation of a shareable link that would allow those with the link to view a draft version of an article. This project would be a complete new feature that could be merged into Joomla 3.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;The details of the user interface would be subject to change/discussion, but could look something like the following:&lt;br /&gt;
A new &amp;quot;Save as Draft&amp;quot; toolbar button on the Articles: Edit page.  When clicked the article will be saved as a draft in the content version history.  The version history page will need to be modified to show this special version of the article.&lt;br /&gt;
A new &amp;quot;Share&amp;quot; toolbar button on the same page.  When clicked, the draft version of the article opens in a new tab with a special URL which can be copy-pasted so that the draft may be shared prior to publication.&lt;br /&gt;
Bonus points for adding a &amp;quot;Preview&amp;quot; toolbar button that will open a new browser tab with a preview of the article currently being edited, without needing to save the article first.&lt;br /&gt;
Code must be accompanied by documentation in the form of wiki pages and full help screens. Code must be accompanied by appropriate tests.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, Joomla CMS&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:theachalaggarwal@gmail.com Achal Aggarwal], [mailto:coolbung@gmail.com Ashwin Date]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project III: Administrator Menu Editor ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;This has been discussed at some length here: https://issues.joomla.org/tracker/joomla-cms/5492&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;An appropriately coded extension that could be merged into Joomla 3.x.&lt;br /&gt;
Code must be accompanied by documentation in the form of wiki pages and full help screens.&lt;br /&gt;
Code must be accompanied by appropriate tests.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, Joomla CMS&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:peter.martin@community.joomla.org Peter Martin], [mailto:tharuna.b@gmail.com Tharuna Balaji]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project IV: Embedded Content Done Right! ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Develop a unified framework for adding any form of embedded content.  A standardised syntax for embedded content tags would be used to call a content plugin that would parse the tag and call plugins in a new embed group to return the appropriate embed code.&lt;br /&gt;
&lt;br /&gt;
This builds on the idea of oembed(http://oembed.com/) but with the capability of overcoming the problems of invalid content associated with some oembed providers.  It is not restricted to oembed providers and can be used to embed any kind of content for which an embed plugin can be written.  Support for new data sources can be added by writing an embed plugin, making it easy for site builders to integrate new embed sources to their sites.  We would gain a powerful, extendable method of embedding content anywhere that supports content plugins.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;An appropriately coded set of plugins that could be merged into Joomla 3.x, including a selection of embed extensions for popular services such as YouTube, Vimeo, Slideshare, Twitter, Facebook, MediaWiki, etc.&lt;br /&gt;
&lt;br /&gt;
Bonus points for writing a JavaScript extension for TinyMCE to make it even easier to embed content.&lt;br /&gt;
&lt;br /&gt;
Code must be accompanied by documentation in the form of wiki pages and full help screens.&lt;br /&gt;
&lt;br /&gt;
Code must be accompanied by appropriate tests.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, Joomla CMS&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Possible mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;NA&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project V: NoSQL Database Driver (Redis, MongoDB) ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;The goal of this is project is to add a lightweight database driver for the most commonly used NoSQL databases (Redis, MongoDB) to the Joomla CMS,&lt;br /&gt;
and not to write yet another ORM, that is outside the scope of this project dued to the 8 weeks timeframe.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Important Links:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;The original pull request: “implementation of Redis caching”  https://github.com/joomla/joomla-cms/pull/3615 merged on Joomla 3.4&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;An open pull request “Redis sessions handler” https://github.com/joomla/joomla-cms/pull/7659&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;The PHP Driver https://github.com/phpredis/phpredis&amp;lt;/td&amp;gt;&amp;lt;tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Starting from version 3.4, Joomla already has a Redis cache management. &lt;br /&gt;
The student is expected to extend the actual cache and session management&lt;br /&gt;
allowing the storage with the NoSQL (mongodb, redis). As a wanted side effect, the code written (drivers) should became  an easy starting point for developers, to write extensions that can store data on NoSQL databases.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Joomla, PHP, SQL, Nosql, data model(relational, key-value, document), Redis, MongoDB, Github&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to Hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:optimus4joomla@gmail.com Nicola Galgano], [mailto:theachalaggarwal@gmail.com Achal Aggarwal]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project VI: Improve Acceptance Tests with PageObjects ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Joomla! currently does not have a viable system test coverage. That leads to regression bugs all the time. The project needs acceptance tests urgently. Using PageObjects as the main concept in this test class will enable us to re-use the tests in future versions, thus to provide better backward compatibility between major versions.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Coverage of the backend pages with PageObjects, Coverage of core frontend pages with PageObjects, A reasonable coverage of the backend with system tests&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, OOP. Basic knowledge about Docker and CodeCeption would be an advantage.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Easy&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:nbraczek@bsds.de Niels Braczek], [mailto:yves@compojoom.com Yves Hoppe]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project VII: Create Menu Item From Article or Other Component ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Return to the old option to Link Menu (V! 1.0.11) facilitating the creation of menus from the creation of an article. Bolder would allow this menu created from other components, such as index search, contact, and even extensions.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;1. Could be a plugin, with an option to choose which parent menu item and the specific content would be linked. &lt;br /&gt;
2. To save the item, add the field to the menu.&lt;br /&gt;
&lt;br /&gt;
3. There could be a inputText to enter the title menu&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, OOP, Javascript&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Easy&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:pedrorenan@gmail.com Pedro Renan], [mailto:ittoufiq@gmail.com Md. Toufiqur Rahman], [mailto:peter.martin@community.joomla.org Peter Martin]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project VIII: Browser Automated Tests for Joomla! CMS (covering Users and Content features) ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;The idea behind the project is to create the system tests for joomla User Management and Content features(For Joomla 3.x). The suggested technology for developing the tests layer is the Codeception Open Source Testing Framework (more info at http://codeception.com). &lt;br /&gt;
&lt;br /&gt;
Test will have to cover the User cases of: creating, editing, removing, publishing articles of content and being modified by different user roles. Also the student is asked to create the integration tests that links the Administrator, the Frontend (by creating menu items) and the Modules and Plugins applications that are related to the Users and Content Features. For example: create an article in frontend, listing all the featured articles, show the articles of an specific category or create a menu item that links to an article.&lt;br /&gt;
&lt;br /&gt;
Joomla is a Mobile Ready CMS, therefore the tests will have to cover different screen resolutions and the different positions of the elements.&lt;br /&gt;
&lt;br /&gt;
The student will have to study the old system tests structure built in the Nearsoft PHP Library and propose a new structure for testing the Joomla Core. The resulting tests need to accomplish the goal of being easily maintainable while being well architectured dividing the responsibilities in scenarios, Pages and Step objects. The mentors will provide the student with code samples that will help the student to achieve the mentioned goals.&lt;br /&gt;
&lt;br /&gt;
To read more about using Codeception with Joomla! Read here: https://docs.joomla.org/Testing_Joomla_Extensions_with_Codeception&lt;br /&gt;
&lt;br /&gt;
More details about the project at https://groups.google.com/d/msg/jgsoc-2016/nzLDqY-chYA/V6ByOHalBQAJ&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;At the end of the project the student should create a Pull request against the Joomla-cms repository (https://github.com/joomla/joomla-cms) providing the system tests for the Users and Content features.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;PHP, object-oriented programming, Joomla CMS (from a user point of view), HTML and basic Git usage.&lt;br /&gt;
&lt;br /&gt;
Value will be given to these candidates that have basic understanding of Selenium, xPath, Codeception framework, Javascript and Knowledge on linux console and Docker Containers.&lt;br /&gt;
&lt;br /&gt;
Is a must for being a candidate for this project to proof that you have been able to run in your local machine the current Webdriver Test Suite. See instructions at https://github.com/joomla-extensions/weblinks#tests&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to Hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:javier.gomez@community.joomla.org Javier Gomez], [mailto:yves@compojoom.com Yves Hoppe]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project IX: One-click Multiple Images Adding Into Article ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Current workflow for adding images to article is costly for human time and efforts: &lt;br /&gt;
1. Before you start create article you have to create folder for new images in Media Manager. &lt;br /&gt;
&lt;br /&gt;
2. At article creating screen you need to open extra window to upload images in necessary folder or in root of media folder.&lt;br /&gt;
&lt;br /&gt;
3. You can upload multiple files here, but you can&#039;t paste more than one image into article, so if you have upload image in path like /2015/02/20/something - you have navigate into this folder again.&lt;br /&gt;
&lt;br /&gt;
And now multiple it on ~10 articles in day.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;One-click multiple images adding into article.&lt;br /&gt;
Image folders should be created automatically by template.&lt;br /&gt;
And as result, end-users are not wasting time with files/folders/pop-ups juggling. &lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Usability, user experience, programmer-free outlook on life.&lt;br /&gt;
PHP, AJAX, Jquery, cross-browser JavaScript.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:shams.bd71@gmail.com Abu Huraira Bin Aman], [mailto:rishi_vishwakarma@hotmail.com Rishi Vishwakarma], [mailto:rob@pollen-8.co.uk Rob Clayburn]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project X: JavaScript Unit Tests ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Joomla uses a collection of custom written JavaScript libraries for its core functionality. This keeps on increasing and it makes it difficult to do enhancements and upgrades for these libraries without conducting extensive manual testing for dependent features in CMS. The goal of this project is to write unit tests for custom JavaScript libraries in Joomla and integrate it with its build system(Travis) to build a solid foundation for future enhancements of these libraries.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Setup a JavaScript Unit Testing framework and a test runner to evaluate Unit Tests on Travis Build. Write Unit Tests to increase the test coverage above 90% for custom JavaScript libraries written for Joomla. Document JavaScript Unit Test Guide for Joomla.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Understanding Unit Testing,  Unit Testing Frameworks for JavaScript, JavaScript, jQuery, PHP, Travis CI&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:ashanf@99x.lk Ashan Fernando]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project XI: Introduction of Accessibility Standards &amp;amp; Code ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Joomla has a lot of accessibility capabilities for visually impaired users but there are a lot of areas where it can improve. Currently there is a lot of work to bring the CMS to WCAG 2.0 AA standards and bringing it closer to being a listed ATAG 2.0 resource for content publishing.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt; All templates distributed in Joomla to meet WCAG 2.0 AA standards&lt;br /&gt;
Template and coding guidelines to help developers create standards compliant code that will meet WCAG 2.0 AA&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Strong front end development skills, bootstrap 2, JS, Joomla dev &amp;amp; accessibility testing and coding skills.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to Hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:akarawuth.t@gmail.com Akarawuth Tamrareang], [mailto:Gunjan.ce2009@gmail.com Gunjan Patel]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Extension Ideas ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Project XI: Larger Joomla ACL publication ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Add to new levels publishing stream: author, reviewer, publisher, supervisor. Where you can determine the profiles, according to the category of the content. essential tool for large projects where there are various teams and responsibilities.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;1. A publishing stream screen, linked to categories (com_categories)&amp;lt;br&amp;gt;&lt;br /&gt;
2. Adding action buttons Approve / Review&amp;lt;br&amp;gt;&lt;br /&gt;
3. Flag for the backend module, to-do items for review / approval, according to the user profile&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;php, oo, javascript&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:roberson.augusto@gmail.com Roberson Augusto], [mailto:nbraczek@bsds.de Niels Braczek]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project XII: Recording actions logs, accessible by super admin ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Store the tasks performed by any user, informing those who did, where did when did and what made within the project.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;A component to map The Croods within the CMS, with filters by date, extension and user&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;php, oo, javascript&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:allan.walker@community.joomla.org Allan Walker], [mailto:llewellyn@vdm.io Llewellyn]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
====Project XIII: Double marking position for modules ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Allow a module to be used in two or more menu items, but in different positions. often módulso need to be duplicated in order to be used in more than one menu item and / or home site. allowing tow module and position + menu reduce the amount of unnecessary duplication&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Option interface to change the position, the selected menu item&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;php, oo, javascript&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Possible mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;NA&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Google Summer of Code 2016]]&lt;br /&gt;
&lt;br /&gt;
====Project XIV: Improve Joomla front and back-end performance through better compatibility with reverse proxies and PageSpeed Module ====&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Brief explanation:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;The CMS Joomla has a good native cache system that improves back-end performance in order to accelerate the HTML generation by 2 to 4 times. With the help of third-party extensions, you can increase the front-end performance (e.g how fast the site seems to load to the user, as well as savings in file transfer), however such extensions can harm back-end performance.&lt;br /&gt;
&lt;br /&gt;
Websites with Joomla CMS focused in high performance, with big amounts of traffic, or with the requirement of generating HTML in less than 100ms, usually use Joomla without performance-enhancing extensions, and implement those tweaks at the webserver level with the PageSpeed module. Furthermore, it is common to employ a caching system like Varnish (or similar) to do a complete ephemeral storage of the resulting HTML response. Such system is greatly appreciated &lt;br /&gt;
&lt;br /&gt;
Joomla, by default (without third-party extensions), does not allow reverse proxy caching. With the use of extensions in Joomla it’s possible, however it&#039;s still not a trivial process nor a pleasant experience, and in some cases - in order to completely disable unnecessary features - might even require changing the core of Joomla, like disabling the use of sessions for guests and hit counts on articles.&lt;br /&gt;
&lt;br /&gt;
This idea is about using the Joomla CMS for what it does best: managing content. To do this we need to trust the cache and HTML/CSS/JS/images optimization to the webserver, in order to allow Joomla to run even faster and spending less money with hosting and CPU time.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Expected Results:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;It is expected that - as an additional option and not by default - you make Joomla able to control the HTTP caching headers to set a different caching time to one or more reverse proxies, just as the cache time sent to the visitor&#039;s browser. This feature should obligatorily be tested and functional for the main reverse proxies that are typically used in the market. Ideally, but not necessarily required, compatibility with services that deliver HTML caching as a service (like possibly CloudFlare and Fastly ®) could also be sought.&lt;br /&gt;
&lt;br /&gt;
If enabled, when a manager create, edit or delete Joomla articles, it will trigger an event to automatically detect major typically changed URLs (for example, the article page itself, the listing page of the categories and the site&#039;s homepage) and thereby allow immediate cache invalidation on those URLs, and on those URLs only, in order to reduce the Joomla administrator’s burden that has to manually invalidate each cached URL- which is a major discouraging aspect of the use of cache invalidation in itself. (Note: The CMS Joomla allows triggers, see https://docs.joomla.org/Plugin/Events)&lt;br /&gt;
&lt;br /&gt;
As to these triggers, it is not required to implement the functionality in a way that automatically use these triggers to effectively invalidate the main reverse proxies’s cache, only allow - in the future - people can use this code base to extend this functionality. However, it tends to be interesting to choose at least one effective example, like Varnish-cache, so this functionality can be througly tested.&lt;br /&gt;
&lt;br /&gt;
Compatibility with Pagespeed Module probably shouldn’t need special changes, but this project should be tested presuming the module is enabled. In case of incompatibilities with the default settings, the produced PHP code should work around these, or there should be produced specific documentation warning about the caveats. A good example of a PageSpeed-related change is to disable content optimizations inside the CMS for specific browsers, such as conversion of images to WEBP - which could provide a cached image that would not work on incompatible browsers.&lt;br /&gt;
&lt;br /&gt;
In addition to the code produced, it is expected that the student create benchmarks comparing before-and-after performance, and also comparing your solution with the solutions using the old native Joomla Caching. At the end of the project, there will be required documentation on how to use the solution, including the provision of configuration suggestions that are relevant to the server, in order to achieve the expected result.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: In additional improvements that changes the Joomla core, which are not needed when you have full page cache like the option to disable hit count in Joomla articles and session creation for guest users, the student will have help from mentors and the Joomla developer community to decide whether it’s worth being implemented. Both this, and other expected results, may change if a strong technical impediment is detected beyond the scope expected for a student during the GSoC period.&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;  &lt;br /&gt;
  &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Knowledge Prerequisite:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;It is recommended to already know how to use a POSIX-like operating system, and it is essential to know how to deal with the command line. You must also have previous knowledge in PHP.&lt;br /&gt;
&lt;br /&gt;
It is not necessary to have prior knowledge with Joomla CMS itself, since this you can learn from us. It is also not required to have previous experience with reverse proxies and the PageSpeed Module, but you must be willing to learn about it, and be pro-active after initial support. Of course, you will have help from mentors in complex situations that will likely arise.&lt;br /&gt;
&lt;br /&gt;
This is more of a DevOps project (https://en.wikipedia.org/wiki/DevOps) than a programmer-only idea. It will be less about just coding in PHP, and will be required to be capable of setting enviroments to test and benchmark the resulting performance. This can be a particularly good project depending on the area you want to work professionally, mainly because having such experience in this area is rar. Finally, it is expected that you have commitment to the idea and the Joomla community.&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt; &lt;br /&gt;
 &amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Difficulty:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;Medium to Hard&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; style=&amp;quot;width:100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&#039;&#039;&#039;Mentors:&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt; &lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;[mailto:emerson@alligo.com.br Emerson Rocha Luiz]&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Gsoc2016.png|50px|center]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[https://groups.google.com/forum/#!forum/jgsoc-2016 For more information please see this mailing list discussion]&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=276724</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=276724"/>
		<updated>2016-02-29T19:49:33Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Running the Test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder structure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder structure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-extensions/weblinks/ com_weblinks] (read about how to fork a repository at https://help.github.com/articles/fork-a-repo/)&lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_weblinks.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Find the complete instructions for running Weblinks tests at: https://github.com/joomla-extensions/weblinks#tests&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/modules/WebDriver#Locating-Elements&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
===Thoughts on Selenium IDE and the codeception Formatter===&lt;br /&gt;
Selenium IDE is a Firefox extension that allows to generate tests in a interactive way:&lt;br /&gt;
&lt;br /&gt;
[[File:Seleniumide.png|thumbnail]]&lt;br /&gt;
&lt;br /&gt;
One can use the [http://www.seleniumhq.org/projects/ide/ Selenium IDE] with the [https://addons.mozilla.org/en-US/firefox/addon/codeception-formatters/ codeception Formatter] to export the tests to Codeception Framework Format.&lt;br /&gt;
&lt;br /&gt;
[[File:exportcodeception.png|thumbnail]]&lt;br /&gt;
 &lt;br /&gt;
Using the Selenium IDE to write the tests seems way easier than writing them in PHP (since you have immediate feedback on what&#039;s going on the page), but it also poses some issues. &lt;br /&gt;
For the most part the Joomla-Browser has functions that we can use to do standard stuff like login, logout etc. If we do our tests with the Selenium IDE we cannot use those and our tests get filled up with stuff that we have already abstracted.&lt;br /&gt;
&lt;br /&gt;
There is still use of the Selenium IDE though, we could use it to create the tests for specific functionality. Like just writing an article, setting publish_up and publish_down dates and then saving. When we export the result with the codeception formatter we would have the necessary PHP and we can add the rest of the stuff for the test to be fully automated (login, navigate to page etc, then execute the exported test). This could speed the creation of tests and we could use non-developers for this kind of work. However this is easier said than done. Due to the Javascript that we use in Joomla simple tests are not that simple. For example clicking in the texteditor and writing text in it is not registered by the IDE since the editor is created by TinyMCE... A way to add text to the editor is to use&lt;br /&gt;
&lt;br /&gt;
 Command | runScript&lt;br /&gt;
 Target | tinyMCE.get(&#039;text_area_id_not_iframe_id&#039;).setContent(&#039;Your text&#039;) &lt;br /&gt;
&lt;br /&gt;
That is again a technical solution to a test that should have been easy in the first place. &lt;br /&gt;
We get into the same trouble with selecting a date out of a Calendar field. So at the end it seems pretty difficult for non-developers to create tests that we could use, because most of the steps recorded by the Selenium IDE won&#039;t work a second time.&lt;br /&gt;
&lt;br /&gt;
If we find a way to make the work with Javascript elements on the page easier, then Selenium IDE could be a great tool that could help us write far more tests, than we currently have in a less time. &lt;br /&gt;
&lt;br /&gt;
As far the codeception Formatter is concerned - it hasn&#039;t been updated in 2 years, but if we find out how to use the Selenium IDE extending the formatter and building on top of it shouldn&#039;t be a show stopper. &lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=276711</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=276711"/>
		<updated>2016-02-29T19:41:01Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* setting up the repository */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder structure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder structure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-extensions/weblinks/ com_weblinks] (read about how to fork a repository at https://help.github.com/articles/fork-a-repo/)&lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_weblinks.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/modules/WebDriver#Locating-Elements&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
===Thoughts on Selenium IDE and the codeception Formatter===&lt;br /&gt;
Selenium IDE is a Firefox extension that allows to generate tests in a interactive way:&lt;br /&gt;
&lt;br /&gt;
[[File:Seleniumide.png|thumbnail]]&lt;br /&gt;
&lt;br /&gt;
One can use the [http://www.seleniumhq.org/projects/ide/ Selenium IDE] with the [https://addons.mozilla.org/en-US/firefox/addon/codeception-formatters/ codeception Formatter] to export the tests to Codeception Framework Format.&lt;br /&gt;
&lt;br /&gt;
[[File:exportcodeception.png|thumbnail]]&lt;br /&gt;
 &lt;br /&gt;
Using the Selenium IDE to write the tests seems way easier than writing them in PHP (since you have immediate feedback on what&#039;s going on the page), but it also poses some issues. &lt;br /&gt;
For the most part the Joomla-Browser has functions that we can use to do standard stuff like login, logout etc. If we do our tests with the Selenium IDE we cannot use those and our tests get filled up with stuff that we have already abstracted.&lt;br /&gt;
&lt;br /&gt;
There is still use of the Selenium IDE though, we could use it to create the tests for specific functionality. Like just writing an article, setting publish_up and publish_down dates and then saving. When we export the result with the codeception formatter we would have the necessary PHP and we can add the rest of the stuff for the test to be fully automated (login, navigate to page etc, then execute the exported test). This could speed the creation of tests and we could use non-developers for this kind of work. However this is easier said than done. Due to the Javascript that we use in Joomla simple tests are not that simple. For example clicking in the texteditor and writing text in it is not registered by the IDE since the editor is created by TinyMCE... A way to add text to the editor is to use&lt;br /&gt;
&lt;br /&gt;
 Command | runScript&lt;br /&gt;
 Target | tinyMCE.get(&#039;text_area_id_not_iframe_id&#039;).setContent(&#039;Your text&#039;) &lt;br /&gt;
&lt;br /&gt;
That is again a technical solution to a test that should have been easy in the first place. &lt;br /&gt;
We get into the same trouble with selecting a date out of a Calendar field. So at the end it seems pretty difficult for non-developers to create tests that we could use, because most of the steps recorded by the Selenium IDE won&#039;t work a second time.&lt;br /&gt;
&lt;br /&gt;
If we find a way to make the work with Javascript elements on the page easier, then Selenium IDE could be a great tool that could help us write far more tests, than we currently have in a less time. &lt;br /&gt;
&lt;br /&gt;
As far the codeception Formatter is concerned - it hasn&#039;t been updated in 2 years, but if we find out how to use the Selenium IDE extending the formatter and building on top of it shouldn&#039;t be a show stopper. &lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=251371</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=251371"/>
		<updated>2015-11-03T12:39:49Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/modules/WebDriver#Locating-Elements&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
===Thoughts on Selenium IDE and the codeception Formatter===&lt;br /&gt;
Selenium IDE is a Firefox extension that allows to generate tests in a interactive way:&lt;br /&gt;
&lt;br /&gt;
[[File:Seleniumide.png|thumbnail]]&lt;br /&gt;
&lt;br /&gt;
One can use the [http://www.seleniumhq.org/projects/ide/ Selenium IDE] with the [https://addons.mozilla.org/en-US/firefox/addon/codeception-formatters/ codeception Formatter] to export the tests to Codeception Framework Format.&lt;br /&gt;
&lt;br /&gt;
[[File:exportcodeception.png|thumbnail]]&lt;br /&gt;
 &lt;br /&gt;
Using the Selenium IDE to write the tests seems way easier than writing them in PHP (since you have immediate feedback on what&#039;s going on the page), but it also poses some issues. &lt;br /&gt;
For the most part the Joomla-Browser has functions that we can use to do standard stuff like login, logout etc. If we do our tests with the Selenium IDE we cannot use those and our tests get filled up with stuff that we have already abstracted.&lt;br /&gt;
&lt;br /&gt;
There is still use of the Selenium IDE though, we could use it to create the tests for specific functionality. Like just writing an article, setting publish_up and publish_down dates and then saving. When we export the result with the codeception formatter we would have the necessary PHP and we can add the rest of the stuff for the test to be fully automated (login, navigate to page etc, then execute the exported test). This could speed the creation of tests and we could use non-developers for this kind of work. However this is easier said than done. Due to the Javascript that we use in Joomla simple tests are not that simple. For example clicking in the texteditor and writing text in it is not registered by the IDE since the editor is created by TinyMCE... A way to add text to the editor is to use&lt;br /&gt;
&lt;br /&gt;
 Command | runScript&lt;br /&gt;
 Target | tinyMCE.get(&#039;text_area_id_not_iframe_id&#039;).setContent(&#039;Your text&#039;) &lt;br /&gt;
&lt;br /&gt;
That is again a technical solution to a test that should have been easy in the first place. &lt;br /&gt;
We get into the same trouble with selecting a date out of a Calendar field. So at the end it seems pretty difficult for non-developers to create tests that we could use, because most of the steps recorded by the Selenium IDE won&#039;t work a second time.&lt;br /&gt;
&lt;br /&gt;
If we find a way to make the work with Javascript elements on the page easier, then Selenium IDE could be a great tool that could help us write far more tests, than we currently have in a less time. &lt;br /&gt;
&lt;br /&gt;
As far the codeception Formatter is concerned - it hasn&#039;t been updated in 2 years, but if we find out how to use the Selenium IDE extending the formatter and building on top of it shouldn&#039;t be a show stopper. &lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=251370</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=251370"/>
		<updated>2015-11-03T12:38:59Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Always add Strict Locators to your tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/modules/WebDriver#Locating-Elements&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
===Thoughts on Selenium IDE and the codeception Formatter===&lt;br /&gt;
Selenium IDE is a Firefox extension that allows to generate tests in a interactive way:&lt;br /&gt;
&lt;br /&gt;
[[File:Seleniumide.png|thumbnail]]&lt;br /&gt;
&lt;br /&gt;
One can use the [http://www.seleniumhq.org/projects/ide/ Selenium IDE] with the [https://addons.mozilla.org/en-US/firefox/addon/codeception-formatters/ codeception Formatter] to export the tests to Codeception Framework Format.&lt;br /&gt;
&lt;br /&gt;
[[File:exportcodeception.png|thumbnail]]&lt;br /&gt;
 &lt;br /&gt;
Using the Selenium IDE to write the tests seems way easier than writing them in PHP (since you have immediate feedback on what&#039;s going on the page), but it also poses some issues. &lt;br /&gt;
For the most part the Joomla-Browser has functions that we can use to do standard stuff like login, logout etc. If we do our tests with the Selenium IDE we cannot use those and our tests get filled up with stuff that we have already abstracted.&lt;br /&gt;
&lt;br /&gt;
There is still use of the Selenium IDE though, we could use it to create the tests for specific functionality. Like just writing an article, setting publish_up and publish_down dates and then saving. When we export the result with the codeception formatter we would have the necessary PHP and we can add the rest of the stuff for the test to be fully automated (login, navigate to page etc, then execute the exported test). This could speed the creation of tests and we could use non-developers for this kind of work. However this is easier said than done. Due to the Javascript that we use in Joomla simple tests are not that simple. For example clicking in the texteditor and writing text in it is not registered by the IDE since the editor is created by TinyMCE... A way to add text to the editor is to use&lt;br /&gt;
&lt;br /&gt;
 Command | runScript&lt;br /&gt;
 Target | tinyMCE.get(&#039;text_area_id_not_iframe_id&#039;).setContent(&#039;Your text&#039;) &lt;br /&gt;
&lt;br /&gt;
That is again a technical solution to a test that should have been easy in the first place. &lt;br /&gt;
We get into the same trouble with selecting a date out of a Calendar field. So at the end it seems pretty difficult for non-developers to create tests that we could use, because most of the steps recorded by the Selenium IDE won&#039;t work a second time.&lt;br /&gt;
&lt;br /&gt;
If we find a way to make the work with Javascript elements on the page easier, then Selenium IDE could be a great tool that could help us write far more tests, than we currently have in a less time. &lt;br /&gt;
&lt;br /&gt;
As far the codeception Formatter is concerned - it hasn&#039;t been updated in 2 years, but if we find out how to use the Selenium IDE extending the formatter and building on top of it shouldn&#039;t be a show stopper. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=File:Exportcodeception.png&amp;diff=250210</id>
		<title>File:Exportcodeception.png</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=File:Exportcodeception.png&amp;diff=250210"/>
		<updated>2015-11-01T12:00:43Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: Selenium IDE export tool to generate Codeception tests&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Selenium IDE export tool to generate Codeception tests&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{JEDL}}&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=File:Seleniumide.png&amp;diff=250209</id>
		<title>File:Seleniumide.png</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=File:Seleniumide.png&amp;diff=250209"/>
		<updated>2015-11-01T11:59:48Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: Selenium IDE tool for testing in Firefox&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Selenium IDE tool for testing in Firefox&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{JEDL}}&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=250208</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=250208"/>
		<updated>2015-11-01T11:58:43Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Thoughts on Selenium IDE and the codeception Formatter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
===Thoughts on Selenium IDE and the codeception Formatter===&lt;br /&gt;
Selenium IDE is a Firefox extension that allows to generate tests in a interactive way:&lt;br /&gt;
&lt;br /&gt;
[[File:Seleniumide.png|thumbnail]]&lt;br /&gt;
&lt;br /&gt;
One can use the [http://www.seleniumhq.org/projects/ide/ Selenium IDE] with the [https://addons.mozilla.org/en-US/firefox/addon/codeception-formatters/ codeception Formatter] to export the tests to Codeception Framework Format.&lt;br /&gt;
&lt;br /&gt;
[[File:exportcodeception.png|thumbnail]]&lt;br /&gt;
 &lt;br /&gt;
Using the Selenium IDE to write the tests seems way easier than writing them in PHP (since you have immediate feedback on what&#039;s going on the page), but it also poses some issues. &lt;br /&gt;
For the most part the Joomla-Browser has functions that we can use to do standard stuff like login, logout etc. If we do our tests with the Selenium IDE we cannot use those and our tests get filled up with stuff that we have already abstracted.&lt;br /&gt;
&lt;br /&gt;
There is still use of the Selenium IDE though, we could use it to create the tests for specific functionality. Like just writing an article, setting publish_up and publish_down dates and then saving. When we export the result with the codeception formatter we would have the necessary PHP and we can add the rest of the stuff for the test to be fully automated (login, navigate to page etc, then execute the exported test). This could speed the creation of tests and we could use non-developers for this kind of work. However this is easier said than done. Due to the Javascript that we use in Joomla simple tests are not that simple. For example clicking in the texteditor and writing text in it is not registered by the IDE since the editor is created by TinyMCE... A way to add text to the editor is to use&lt;br /&gt;
&lt;br /&gt;
 Command | runScript&lt;br /&gt;
 Target | tinyMCE.get(&#039;text_area_id_not_iframe_id&#039;).setContent(&#039;Your text&#039;) &lt;br /&gt;
&lt;br /&gt;
That is again a technical solution to a test that should have been easy in the first place. &lt;br /&gt;
We get into the same trouble with selecting a date out of a Calendar field. So at the end it seems pretty difficult for non-developers to create tests that we could use, because most of the steps recorded by the Selenium IDE won&#039;t work a second time.&lt;br /&gt;
&lt;br /&gt;
If we find a way to make the work with Javascript elements on the page easier, then Selenium IDE could be a great tool that could help us write far more tests, than we currently have in a less time. &lt;br /&gt;
&lt;br /&gt;
As far the codeception Formatter is concerned - it hasn&#039;t been updated in 2 years, but if we find out how to use the Selenium IDE extending the formatter and building on top of it shouldn&#039;t be a show stopper. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=249966</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=249966"/>
		<updated>2015-10-31T11:55:15Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Always add Strict Locators to your tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=249965</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=249965"/>
		<updated>2015-10-31T11:54:26Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Always add Strict Locators to your tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
&lt;br /&gt;
Allowed locator mechanisms are:&lt;br /&gt;
&lt;br /&gt;
- [&#039;id&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;name&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;css&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;xpath&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;link&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
- [&#039;class&#039; =&amp;gt; &#039;xxx&#039;]&lt;br /&gt;
&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=247631</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=247631"/>
		<updated>2015-10-28T09:28:50Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* How much time should I wait for an Element or Text? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;60&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 60 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
If a waitForText command takes over 10 seconds, it will much probably mean that something is not performing well. Maybe a non [[Testing Joomla Extensions with Codeception#Always_add_Strict_Locators_to_your_tests|Strict Locator]] is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Needs to be marked for translation]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Code_sprints&amp;diff=241429</id>
		<title>Code sprints</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Code_sprints&amp;diff=241429"/>
		<updated>2015-10-14T12:08:20Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&amp;lt;languages /&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
A code sprint is a dedicated session in which a group of volunteers come together at a geographic location to work on code for the Joomla project. Examples of code sprint sessions could include UI/UX improvements, working on new features, or long term planning and architecture work. Typically, six to ten experienced individuals will be brought together for two days for these events. If you wish to form your own sprint then read the [[S:MyLanguage/Joomla:Sprint_Policy|policy]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
The code sprints are organised by the Joomla community together with the Production Leadership Team. These events are supported by the OpenSourceMatters and other sponsors.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
Code Sprints in 2013:&lt;br /&gt;
* &#039;&#039;&#039;Rapid Application Development Code Sprint&#039;&#039;&#039;, July 2013, Pistoia, Italy&lt;br /&gt;
* &#039;&#039;&#039;Code stability and bug triage Code Sprint&#039;&#039;&#039;, Aug 2013, Nashville, Tennessee, USA. More info:&lt;br /&gt;
&amp;lt;/translate&amp;gt; http://community.joomla.org/blogs/leadership/1757-call-for-participants-for-code-sprint.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Code Sprints in 2014:&lt;br /&gt;
* &#039;&#039;&#039;Architecture Sprint&#039;&#039;&#039;, Feb 8-9, San Jose, California, USA.&lt;br /&gt;
* &#039;&#039;&#039;Bug Clean Up Sprint&#039;&#039;&#039;, July 26-27, More info: http://magazine.joomla.org/issues/issue-aug-2014/item/2228-joomla-bug-sprint-in-manchester&lt;br /&gt;
* &#039;&#039;&#039;Code Style Code Sprint&#039;&#039;&#039;, Oct 11-12, Madrid, Spain.  More info at: http://magazine.joomla.org/issues/issue-nov-2014/item/2353-two-joomla-code-sprints&lt;br /&gt;
* &#039;&#039;&#039;Code Testing Code Sprint&#039;&#039;&#039;, Oct 14, Montabaur, Germany. More info at: http://thephp.cc/viewpoints/blog/2014/10/joomla-phpunit-code-sprint&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code Sprints in 2015:&lt;br /&gt;
* &#039;&#039;&#039;Joomla 4 Architecture Sprint&#039;&#039;&#039;, July 10-12, Odense, Denmark. More info at: http://volunteers.joomla.org/reports/115-joomla-4-architecture-sprint-odense-dk&lt;br /&gt;
* &#039;&#039;&#039;Joomla 4 UX and Architecture Sprint&#039;&#039;&#039;, October 10-12, Athens, Greece.&lt;br /&gt;
* &#039;&#039;&#039;Joomla! Automated Testing Code Sprint&#039;&#039;&#039;, October 28th - November 2nd, Karlsruhe, Germany.&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
[[Category:Events]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Joomla_info_page/es-ES&amp;diff=240403</id>
		<title>Joomla info page/es-ES</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Joomla_info_page/es-ES&amp;diff=240403"/>
		<updated>2015-10-08T12:11:36Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: removing http://joomlaspanish.org since is not anymore available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Spanish =&lt;br /&gt;
&lt;br /&gt;
== ¿Qué es Joomla? ==&lt;br /&gt;
Joomla es un premiado sistema de Gestión de Contenidos (CMS), que permite crear sitios Web y poderosas aplicaciones online. Muchos aspectos, incluyendo su fácil uso y extensibilidad han convertido a Joomla! en el software para Web más popular. Y lo mejor de todo, Joomla es Software Libre disponible gratuitamente para todo el mundo. Entre los beneficios de Joomla se incluye:&lt;br /&gt;
&lt;br /&gt;
* Fácil instalación&lt;br /&gt;
* Simple mantenimiento del web&lt;br /&gt;
* Seguridad y estabilidad&lt;br /&gt;
* Potentes extensiones comerciales y gratuitas&lt;br /&gt;
* Una enorme cantidad de plantillas para cambiar fácilmente el look de tu web.&lt;br /&gt;
&lt;br /&gt;
Tienes más información sobre Joomla! en español [http://docs.joomla.org/Joomla_brochure/es-ES en este otro artículo de la documentación].&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir Joomla? ==&lt;br /&gt;
* Descarga Joomla! desde los [http://www.joomla.org/download.html repositorios oficiales].&lt;br /&gt;
* Descarga los paquetes de idioma español de los [http://community.joomla.org/translations.html grupos de traducción acreditados] desde aquí: &lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=30 Paquetes de la rama 1.5.x]&lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation1_6/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=5597 Paquetes de la rama 2.5.x]&lt;br /&gt;
** [http://joomlacode.org/gf/project/jtranslation3_x/frs/?action=FrsReleaseBrowse&amp;amp;frs_package_id=6445 Paquetes de la rama 3.0.x]&lt;br /&gt;
* Otras traducciones&lt;br /&gt;
** [http://joomlacode.org/gf/project/spanishlanguage/frs/ Traducciones más antiguas del grupo acreditado anterior (incluye traducciones de la rama 1.0.x)]&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde descargar extensiones? ==&lt;br /&gt;
* Descarga extensiones en: http://extensions.joomla.org/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir documentación para Joomla? ==&lt;br /&gt;
* Documentación en inglés: http://docs.joomla.org/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ¿Dónde conseguir soporte/ayuda para Joomla? ==&lt;br /&gt;
* Soporte gratuito en Inglés: http://forum.joomla.org/&lt;br /&gt;
* Soporte gratuito en Español: &lt;br /&gt;
** http://forum.joomla.org/viewforum.php?f=24&lt;br /&gt;
** http://magazine.joomla.org/international-stories-all/articles-in-spanish-all&lt;br /&gt;
* Soporte gratuito en lugares no oficiales:&lt;br /&gt;
** http://foro.comunidadjoomla.org&lt;br /&gt;
* Soporte comercial: http://resources.joomla.org/ (website en Inglés)&lt;br /&gt;
&lt;br /&gt;
== Eventos regionales / Joomladays ==&lt;br /&gt;
Las comunidades locales organizan eventos Joomla! conocidos como &#039;&#039;Joomla!Days&#039;&#039; por todo el mundo. Un Joomla Day es un evento creado exclusivamente para los usuarios de Joomla! y sus proyectos relacionados. Habitualmente tienen una audiencia regional. Más información en: http://events.joomla.org/joomla-days.html&lt;br /&gt;
&lt;br /&gt;
== Joomla User Groups (JUG) ==&lt;br /&gt;
Los Grupos de usuarios de Joomla (JUG) son una manera magnífica de conocer gente, conseguir ayuda para un proyecto, o compartir las experiencias con otros usuarios de Joomla. Joomla! está en todos los lugares del mundo así que revisa si ya existe algún JUG en tu zona. En caso contrario, ¿Por qué no creas uno?&lt;br /&gt;
&lt;br /&gt;
* JUGs en Centro América: http://community.joomla.org/user-groups/central-america.html&lt;br /&gt;
* JUGs en el Caribe: http://community.joomla.org/user-groups/caribbean.html&lt;br /&gt;
* JUGs en Sud América: http://community.joomla.org/user-groups/south-america.html&lt;br /&gt;
* JUGs España: http://community.joomla.org/user-groups/europe/spain.html&lt;br /&gt;
&lt;br /&gt;
* Preguntas frecuentes JUG: http://community.joomla.org/jug-faq-spanish.html&lt;br /&gt;
&lt;br /&gt;
== ¿Cómo puedes apoyar a Joomla!? ==&lt;br /&gt;
* Responde dudas de otras personas en los foros&lt;br /&gt;
* Escribe o traduce un tutorial o documentación&lt;br /&gt;
* Desarrolla una Extensión o una plantilla de diseño&lt;br /&gt;
* Testea y comunica los errores que encuentres&lt;br /&gt;
* Únete a un equipo de trabajo Joomla!&lt;br /&gt;
* Colabora en la organización y participa en los eventos Joomla!&lt;br /&gt;
* Apoya económicamente o de otras maneras: http://contribute.joomla.org/&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=236606</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=236606"/>
		<updated>2015-09-28T09:19:21Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Do not leave spaces between parameters in Cepts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;30&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 30 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
A waitForText over 10 seconds will definitely mean that something is not performing well. Maybe a non strict Locator is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Write complex locator VS. modifying the output of the tested website===&lt;br /&gt;
Sometimes we need to write a very complex xpath to locate a element in the page, for example: &lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;xpath&#039; =&amp;gt;  &amp;quot;//*[@id=\&amp;quot;menuList\&amp;quot;]/tbody/tr/td[2]/a[contains(text(), &#039;weblink&#039;)&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
wouldn&#039;t be much better to write something like this instead?&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click([&#039;class&#039; =&amp;gt;  &amp;quot;lc-menu_item_type_weblinks&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
When you find yourself writting a very complex locator in a test, is maybe because the markup of the Website is wrong. For this cases, is better to stop writing the test and reconsider the possibility of modifying the website that we are testing. There is nothing that prevents us to improve Joomla markup. Actually is the other way arround, with these fixes we are probably making Joomla more accessible.&lt;br /&gt;
We have had experiences in the past, see for example this issue: https://github.com/joomla/joomla-cms/issues/7207. &lt;br /&gt;
&lt;br /&gt;
In conclusion is much more convenient to add just a simple class to the element to easily locate it instead of becoming mad finding the right xPath. Remind that is important that our tests are readable, and that has to do with using readable locators. &lt;br /&gt;
&lt;br /&gt;
In order to simplify locators used in Acceptance tests we add special locator classes into HTML of web pages. So not to confuse them with classes needed by CSS or JavaScript we use &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix. Thus, if you find locator to be to complex, it would be much easier to edit HTML and add a new class into it.&lt;br /&gt;
&lt;br /&gt;
 $I-&amp;gt;click(&#039;class&#039; =&amp;gt;  &amp;quot;lc-comment-delete&#039;);&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;lc&#039;&#039; stands for &#039;&#039;locator&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Is important that the rest of Joomla coders know that this &#039;&#039;&#039;lc-&#039;&#039;&#039; prefix is used by the tests to prevent anyone from removing it.&lt;br /&gt;
&lt;br /&gt;
This recommendation was originally suggested by Davert (the creator of Codeception) at http://phptest.club/t/codeception-tips-tricks/14/8.&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=J3.x:Making_a_Language_Pack_for_Joomla&amp;diff=209454</id>
		<title>J3.x:Making a Language Pack for Joomla</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=J3.x:Making_a_Language_Pack_for_Joomla&amp;diff=209454"/>
		<updated>2015-07-29T14:54:53Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: Add FAQ to language package creation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&amp;lt;languages /&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;{{Joomla version|version=3.x|comment=&amp;lt;translate&amp;gt;&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
series&amp;lt;/translate&amp;gt;}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{-}}&lt;br /&gt;
{{RightTOC}}&lt;br /&gt;
&amp;lt;translate&amp;gt;==How to create localized CORE language packs== &amp;lt;!--T:1--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
===Notes=== &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
* ALL FILES MUST BE SAVED AS UTF8 NO BOM (for non-ascii glyphs as in accented letters, etc.) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
* The [http://extensions.joomla.org/extensions/languages/language-edition/17755 Localise] component may help you create and update the ini files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
* For 3rd party extensions self-contained ini files installation in Joomla 2.5, see [[S:MyLanguage/J2.5:Making non-core language packs|J2.5:Making non-core language packs]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
* For Joomla 2.5 core language packs, see [[S:MyLanguage/J2.5:Making a Language Pack for Joomla|J2.5:Making a Language Pack for Joomla!]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
* As of Joomla! 3.2.0, en-GB is always loading first. Therefore if a string is missing or if there is a parsing error in a language pack, the English value will be displayed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
* Current Joomla development can be fetched from the [https://github.com/joomla/joomla-cms Home of the Joomla! Content Management System at Github]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
==Full language packs== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;* &amp;lt;code&amp;gt;fr-FR&amp;lt;code&amp;gt; is taken as an example of language prefix.&#039;&#039;&#039;&lt;br /&gt;
A full language pack will contain translations for site and admin parts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
# In the case of a &#039;&#039;&#039;FULL&#039;&#039;&#039; pack, the package is composed of 3 files, then zipped.&lt;br /&gt;
#* &amp;lt;code&amp;gt;pkg_fr-FR.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;site_fr-FR.zip&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;admin_fr-FR.zip&amp;lt;/code&amp;gt;&lt;br /&gt;
# Naming of the pack&lt;br /&gt;
#* &#039;&#039;&#039;fr-FR_joomla_lang_full_3.4.1v1.zip&#039;&#039;&#039;&lt;br /&gt;
# Files required for partial deletion&lt;br /&gt;
#* each pack should include a &amp;lt;code&amp;gt;fr-FR.lib_joomla.ini&amp;lt;/code&amp;gt; and a &amp;lt;code&amp;gt;fr-FR.localise.php&amp;lt;/code&amp;gt; to cope for deletion of site or admin pack by the user.&lt;br /&gt;
#* &#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;: Since some administrator ini files are necessary in front-end and some changes were brought in the loading of the plugin ini files, it is always necessary to include some admin part in the final pack, even for a &#039;&#039;&#039;&#039;site-only&#039;&#039;&#039;&#039; pack. See below [[#The Site-only pack|The Site-only pack]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;===A pkg_fr-FR.xml file=== &amp;lt;!--T:11--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;extension type=&amp;quot;package&amp;quot; version=&amp;quot;3.4&amp;quot; method=&amp;quot;upgrade&amp;quot;&amp;gt; &amp;lt;! method=&amp;quot;upgrade&amp;quot; is compulsory since 3.4 --&amp;gt;&lt;br /&gt;
	&amp;lt;name&amp;gt;French_fr-FR&amp;lt;/name&amp;gt;&lt;br /&gt;
	&amp;lt;packagename&amp;gt;fr-FR&amp;lt;/packagename&amp;gt; &amp;lt;!-- the packagename has to be the same as the name of pkg_whatever.xml --&amp;gt;&lt;br /&gt;
	&amp;lt;version&amp;gt;3.4.1.1&amp;lt;/version&amp;gt; &amp;lt;!-- change the version # 3.x.x.x when updating, will display in manager --&amp;gt;&lt;br /&gt;
	&amp;lt;creationDate&amp;gt;03/03/2015&amp;lt;/creationDate&amp;gt; &amp;lt;!-- will display in manager --&amp;gt;&lt;br /&gt;
	&amp;lt;author&amp;gt;French translation team : joomla.fr&amp;lt;/author&amp;gt; &amp;lt;!-- will display in manager --&amp;gt;&lt;br /&gt;
	&amp;lt;authorEmail&amp;gt;traduction@joomla.fr&amp;lt;/authorEmail&amp;gt; &amp;lt;!-- will display in manager --&amp;gt;&lt;br /&gt;
	&amp;lt;authorUrl&amp;gt;http://joomla.fr&amp;lt;/authorUrl&amp;gt; &amp;lt;!-- will display in manager --&amp;gt;&lt;br /&gt;
	&amp;lt;copyright&amp;gt;Copyright (C) 2005 - 2015 Joomla.fr and Open Source Matters, Inc. All rights reserved.&amp;lt;/copyright&amp;gt;&lt;br /&gt;
	&amp;lt;license&amp;gt;http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL&amp;lt;/license&amp;gt;&lt;br /&gt;
	&amp;lt;url&amp;gt;&amp;lt;/url&amp;gt;&lt;br /&gt;
	&amp;lt;packager&amp;gt;&amp;lt;/packager&amp;gt;&lt;br /&gt;
	&amp;lt;packagerurl&amp;gt;&amp;lt;/packagerurl&amp;gt;&lt;br /&gt;
	&amp;lt;description&amp;gt;&amp;lt;![CDATA[&amp;lt;div style=&amp;quot;text-align:left;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Joomla! 3.4.1 Full French (fr-FR) Language Package - Version 3.4.1v1&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Paquet de langue Joomla! 3.4.1 français (fr-FR) complet - Version 3.4.1v1&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;]]&amp;gt;&amp;lt;/description&amp;gt;&lt;br /&gt;
	&amp;lt;files&amp;gt;&lt;br /&gt;
		&amp;lt;file type=&amp;quot;language&amp;quot; client=&amp;quot;site&amp;quot; id=&amp;quot;fr-FR&amp;quot;&amp;gt;site_fr-FR.zip&amp;lt;/file&amp;gt;&lt;br /&gt;
		&amp;lt;file type=&amp;quot;language&amp;quot; client=&amp;quot;administrator&amp;quot; id=&amp;quot;fr-FR&amp;quot;&amp;gt;admin_fr-FR.zip&amp;lt;/file&amp;gt;&lt;br /&gt;
	&amp;lt;/files&amp;gt;&lt;br /&gt;
	&amp;lt;updateservers&amp;gt;&lt;br /&gt;
		&amp;lt;server type=&amp;quot;collection&amp;quot; priority=&amp;quot;1&amp;quot; name=&amp;quot;Accredited Joomla! Translations&amp;quot;&amp;gt;http://update.joomla.org/language/translationlist_3.xml&amp;lt;/server&amp;gt;&lt;br /&gt;
	&amp;lt;/updateservers&amp;gt;&lt;br /&gt;
&amp;lt;/extension&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Note: TinyMCE files are no more needed for 3.2. They are now shipped with core. If your language is missing, please contact the Translation Team coordination.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
===One zip per client (i.e. site and admin)=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;site_fr-FR.zip&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;admin_fr-FR.zip&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Content of the client&#039;s zip (example below is for admin)&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
====an install.xml ==== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
Example for admin&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;extension version=&amp;quot;3.4&amp;quot; client=&amp;quot;administrator&amp;quot; type=&amp;quot;language&amp;quot; method=&amp;quot;upgrade&amp;quot;&amp;gt; // change to client=&amp;quot;site&amp;quot; if site pack&lt;br /&gt;
	&amp;lt;name&amp;gt;French (fr-FR)&amp;lt;/name&amp;gt;&lt;br /&gt;
	&amp;lt;tag&amp;gt;fr-FR&amp;lt;/tag&amp;gt;&lt;br /&gt;
	&amp;lt;version&amp;gt;3.4.1.1&amp;lt;/version&amp;gt;&lt;br /&gt;
	&amp;lt;creationDate&amp;gt;15/05/2013&amp;lt;/creationDate&amp;gt;&lt;br /&gt;
	&amp;lt;author&amp;gt;French translation team : joomla.fr&amp;lt;/author&amp;gt;&lt;br /&gt;
	&amp;lt;authorEmail&amp;gt;traduction@joomla.fr&amp;lt;/authorEmail&amp;gt;&lt;br /&gt;
	&amp;lt;authorUrl&amp;gt;www.joomla.fr&amp;lt;/authorUrl&amp;gt;&lt;br /&gt;
	&amp;lt;copyright&amp;gt;Copyright (C) 2005 - 2013 joomla.fr et Open Source Matters. Tous droits réservés&amp;lt;/copyright&amp;gt;&lt;br /&gt;
	&amp;lt;license&amp;gt;GNU General Public License version 2 or later; see LICENSE.txt&amp;lt;/license&amp;gt;&lt;br /&gt;
	&amp;lt;description&amp;gt;fr-FR administrator language&amp;lt;/description&amp;gt;&lt;br /&gt;
	&amp;lt;files&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;index.html&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_admin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_admin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_banners.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_banners.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_ajax.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_ajax.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_cache.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_cache.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_checkin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_checkin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_config.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_config.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_contact.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_contact.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_contenthistory.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_contenthistory.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_cpanel.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_cpanel.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_finder.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_finder.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_installer.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_installer.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_joomlaupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_joomlaupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_languages.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_languages.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_login.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_login.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_mailto.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_media.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_media.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_menus.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_menus.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_messages.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_messages.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_modules.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_modules.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_plugins.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_plugins.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_postinstall.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_postinstall.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_redirect.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_redirect.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_search.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_search.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_templates.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_templates.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_users.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_users.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_wrapper.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.com_wrapper.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
                &amp;lt;filename&amp;gt;fr-FR.css&amp;lt;/filename&amp;gt; &amp;lt;!-- this file can be added in the ADMINISTRATOR pack if one wants to change the fonts used to display the back-end interface.--&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.lib_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.localise.php&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_custom.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_custom.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_feed.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_feed.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_latest.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_latest.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_logged.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_logged.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_login.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_login.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_menu.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_menu.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_multilangstatus.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_multilangstatus.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_popular.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_popular.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_quickicon.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_quickicon.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_stats_admin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_stats_admin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_status.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_status.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_submenu.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_submenu.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_title.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_title.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_toolbar.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_toolbar.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_version.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.mod_version.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_cookie.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_cookie.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_gmail.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_gmail.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_ldap.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_authentication_ldap.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_captcha_recaptcha.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_captcha_recaptcha.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_emailcloak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_emailcloak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_finder.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_finder.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_loadmodule.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_loadmodule.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_pagebreak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_pagebreak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_pagenavigation.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_pagenavigation.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_vote.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_content_vote.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_codemirror.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_codemirror.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_none.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_none.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_tinymce.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors_tinymce.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_article.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_article.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_image.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_image.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_pagebreak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_pagebreak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_readmore.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_editors-xtd_readmore.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_extension_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_extension_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_contacts.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_contacts.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_finder_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_installer_webinstaller.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_installer_webinstaller.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_quickicon_extensionupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_quickicon_extensionupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_quickicon_joomlaupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_quickicon_joomlaupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_contacts.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_contacts.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_search_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_cache.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_cache.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_debug.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_debug.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_highlight.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_highlight.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_languagecode.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_languagecode.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_languagefilter.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_languagefilter.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_log.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_log.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_logout.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_logout.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_p3p.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_p3p.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_redirect.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_redirect.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_remember.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_remember.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_sef.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_system_sef.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_twofactorauth_totp.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_twofactorauth_totp.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_twofactorauth_yubikey.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_twofactorauth_yubikey.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_contactcreator.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_contactcreator.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_profile.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.plg_user_profile.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.tpl_hathor.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.tpl_hathor.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.tpl_isis.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;fr-FR.tpl_isis.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename file=&amp;quot;meta&amp;quot;&amp;gt;install.xml&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename file=&amp;quot;meta&amp;quot;&amp;gt;fr-FR.xml&amp;lt;/filename&amp;gt;&lt;br /&gt;
	&amp;lt;/files&amp;gt;&lt;br /&gt;
	&amp;lt;media destination=&amp;quot;fr-FR&amp;quot;&amp;gt;  &amp;lt;!-- If one needs to add a specific calendar --&amp;gt;&lt;br /&gt;
	    &amp;lt;filename&amp;gt;index.html&amp;lt;/filename&amp;gt;&lt;br /&gt;
	    &amp;lt;filename&amp;gt;js/index.html&amp;lt;/filename&amp;gt;&lt;br /&gt;
	    &amp;lt;filename&amp;gt;js/calendar-setup.js&amp;lt;/filename&amp;gt;&lt;br /&gt;
	    &amp;lt;filename&amp;gt;js/calendar.js&amp;lt;/filename&amp;gt;&lt;br /&gt;
	&amp;lt;/media&amp;gt;&lt;br /&gt;
	&amp;lt;params /&amp;gt;&lt;br /&gt;
&amp;lt;/extension&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Notes: &lt;br /&gt;
* &amp;lt;code&amp;gt;fr-FR.lib_joomla.ini&amp;lt;/code&amp;gt; : Add in both admin and site At least in site if &amp;quot;site only pack&amp;quot;, see below&lt;br /&gt;
* &amp;lt;code&amp;gt;fr-FR.css&amp;lt;/code&amp;gt; : NEW IN 1.7: this file can be added in the ADMINISTRATOR pack if one wants to change the fonts used to display the back-end interface.&lt;br /&gt;
* &amp;lt;code&amp;gt;fr-FR.xml&amp;lt;/code&amp;gt; : Note the file=&amp;quot;meta&amp;quot; tag, telling it&#039;s the basic xml holding info about the pack.&lt;br /&gt;
* &amp;lt;code&amp;gt;install.xml&amp;lt;/code&amp;gt; : Mandatory! This file lets install/uninstall a language. Note file=&amp;quot;meta&amp;quot;&lt;br /&gt;
* &amp;lt;code&amp;gt;fr-FR.localise.php&amp;lt;/code&amp;gt; : Add in both admin and site. At least in site if &amp;quot;site only pack&amp;quot;, see below&lt;br /&gt;
* Folder media &amp;lt;code&amp;gt;destination=&amp;quot;fr-FR&amp;quot;&amp;lt;/code&amp;gt; : If one needs to add a specific calendar&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
====All the ini files==== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Beware of new formatting! &lt;br /&gt;
* Double quotes in the value should be written as &amp;quot;_QQ_&amp;quot; or as &amp;amp;amp;quot;&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
====the fr-FR.xml==== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;metafile version=&amp;quot;3.2&amp;quot; client=&amp;quot;administrator&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;fr-FR&amp;lt;/tag&amp;gt;&lt;br /&gt;
	&amp;lt;name&amp;gt;French (fr-FR)&amp;lt;/name&amp;gt;&lt;br /&gt;
	&amp;lt;version&amp;gt;3.4.1.1&amp;lt;/version&amp;gt;&lt;br /&gt;
	&amp;lt;creationDate&amp;gt;15/04/2013&amp;lt;/creationDate&amp;gt;&lt;br /&gt;
	&amp;lt;author&amp;gt;French translation team : joomla.fr&amp;lt;/author&amp;gt;&lt;br /&gt;
	&amp;lt;authorEmail&amp;gt;traduction@joomla.fr&amp;lt;/authorEmail&amp;gt;&lt;br /&gt;
	&amp;lt;authorUrl&amp;gt;www.joomla.fr&amp;lt;/authorUrl&amp;gt;&lt;br /&gt;
	&amp;lt;copyright&amp;gt;Copyright (C) 2005 - 2013 Open Source Matters &amp;amp;amp; Joomla.fr. All rights reserved.&amp;lt;/copyright&amp;gt;&lt;br /&gt;
	&amp;lt;license&amp;gt;GNU General Public License version 2 or later; see LICENSE.txt&amp;lt;/license&amp;gt;&lt;br /&gt;
	&amp;lt;description&amp;gt;French administrator language for Joomla 3.0&amp;lt;/description&amp;gt;&lt;br /&gt;
	&amp;lt;metadata&amp;gt;&lt;br /&gt;
		&amp;lt;name&amp;gt;Français (FR)&amp;lt;/name&amp;gt;&lt;br /&gt;
		&amp;lt;tag&amp;gt;fr-FR&amp;lt;/tag&amp;gt;&lt;br /&gt;
		&amp;lt;rtl&amp;gt;0&amp;lt;/rtl&amp;gt;&lt;br /&gt;
		&amp;lt;locale&amp;gt;fr_FR.utf8, fr_FR.UTF-8, fr_FR.UTF-8@euro, fr_FR, fre_FR, fr, france&amp;lt;/locale&amp;gt;&lt;br /&gt;
		&amp;lt;firstDay&amp;gt;1&amp;lt;/firstDay&amp;gt;&lt;br /&gt;
		&amp;lt;weekEnd&amp;gt;0,6&amp;lt;/weekEnd&amp;gt;&lt;br /&gt;
	&amp;lt;/metadata&amp;gt;&lt;br /&gt;
	&amp;lt;params /&amp;gt;&lt;br /&gt;
&amp;lt;/metafile&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
Notes:&lt;br /&gt;
* &amp;lt;locale&amp;gt; the locale is used to sort translated lists when present on the server.&lt;br /&gt;
* &amp;lt;firstDay&amp;gt;1&amp;lt;/firstDay&amp;gt; used for the Calendar icon to specify what is the first day of the week in that language. 0 is Sunday, 1 is Monday, etc.&lt;br /&gt;
* &amp;lt;weekEnd&amp;gt;0,6&amp;lt;/weekEnd&amp;gt; used for the Calendar, I defines the days of the week to be greyed. 0,6 is Saturday &amp;amp; Sunday, 1 would be Friday.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
====the fr-FR.localise.php==== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This file should be present at least in site zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Explanation of this file: It replaces the &amp;lt;code&amp;gt;fr-FR.ignore.php&amp;lt;/code&amp;gt; and it can be customized depending on languages.&lt;br /&gt;
 &lt;br /&gt;
*Ignore search words.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
*Define upper and lower limit of search words length.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
*Define number of characters to display for the result of the search.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
*Define specific plural functionality for some languages where the value of the string can change depending on the count (Russian for example).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
*Define custom transliteration (i.e. when NOT using the Unicode URLS parameter in Global Configuration) to ensure proper change of some alphabets to ascii for the alias used when SEF is on. (The transliteration which is now default in 1.7 should take care of all latin-based languages.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
*Define a custom calendar by adding a function as well as some js files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;ALWAYS SAVE THIS FILE AS UTF8 NO BOM&#039;&#039;&#039; if it contains non-ascii glyphs (accented letters, etc.)&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
=====Example 1 - Custom transliteration NOT implemented===== &amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
Example of a basic &amp;lt;code&amp;gt;fr-FR.localise.php&amp;lt;/code&amp;gt; (where custom transliteration is NOT implemented)&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * @version		$Id: fr-FR.localise.php 15628 2010-03-27 05:20:29Z infograf768 $&lt;br /&gt;
 * @copyright	Copyright (C) 2005 - 2010 Open Source Matters, Inc. All rights reserved.&lt;br /&gt;
 * @license		GNU General Public License version 2 or later; see LICENSE.txt&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * fr-FR localise class&lt;br /&gt;
 *&lt;br /&gt;
 * @package		Joomla.Site&lt;br /&gt;
 * @since		1.6&lt;br /&gt;
 */&lt;br /&gt;
abstract class Fr_FRLocalise {    //// !!!! NOTE the use of Fr_FR for the class !!!  // not the same as your language prefix.&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the potential suffixes for a specific number of items&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param	int $count  The number of items.&lt;br /&gt;
	 * @return	array  An array of potential suffixes.&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function getPluralSuffixes($count) {&lt;br /&gt;
		if ($count == 0) {&lt;br /&gt;
			$return =  array(&#039;0&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		elseif($count == 1) {&lt;br /&gt;
			$return =  array(&#039;1&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		else {&lt;br /&gt;
			$return = array(&#039;MORE&#039;);  // Beware, this will be added to a language KEY. It should be in ascii and Uppercase.&lt;br /&gt;
		}&lt;br /&gt;
		return $return;&lt;br /&gt;
	}&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the ignored search words&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return	array  An array of ignored search words.&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function getIgnoredSearchWords() {&lt;br /&gt;
		$search_ignore = array();&lt;br /&gt;
		$search_ignore[] = &amp;quot;et&amp;quot;;&lt;br /&gt;
		$search_ignore[] = &amp;quot;si&amp;quot;;&lt;br /&gt;
		$search_ignore[] = &amp;quot;ou&amp;quot;;&lt;br /&gt;
		return $search_ignore;&lt;br /&gt;
	}&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the lower length limit of search words&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return	integer  The lower length limit of search words.&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function getLowerLimitSearchWord() {&lt;br /&gt;
		return 3;&lt;br /&gt;
	}&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the upper length limit of search words&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return	integer  The upper length limit of search words.&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function getUpperLimitSearchWord() {&lt;br /&gt;
		return 20;&lt;br /&gt;
	}&lt;br /&gt;
	/**&lt;br /&gt;
	 * Returns the number of chars to display when searching&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return	integer  The number of chars to display when searching.&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function getSearchDisplayedCharactersNumber() {&lt;br /&gt;
		return 200;&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
=====Example 2 - Custom transliteration implemented===== &amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
Example of the function to add to file &amp;lt;code&amp;gt;localise.php&amp;lt;/code&amp;gt; when custom transliteration is desired&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
	 * This method processes a string and replaces all accented UTF-8 characters by unaccented&lt;br /&gt;
	 * ASCII-7 &amp;quot;equivalents&amp;quot;&lt;br /&gt;
	 *&lt;br /&gt;
	 * @param	string	$string	The string to transliterate&lt;br /&gt;
	 * @return	string	The transliteration of the string&lt;br /&gt;
	 * @since	1.6&lt;br /&gt;
	 */&lt;br /&gt;
	public static function transliterate($string)&lt;br /&gt;
		{&lt;br /&gt;
		$str = JString::strtolower($string);&lt;br /&gt;
&lt;br /&gt;
		//Specific language transliteration.&lt;br /&gt;
		//This one is for latin 1, latin supplement , extended A, Cyrillic, Greek&lt;br /&gt;
&lt;br /&gt;
		$glyph_array = array(&lt;br /&gt;
		&#039;a&#039;		=&amp;gt;	&#039;a,à,á,â,ã,ä,å,ā,ă,ą,ḁ,α,ά&#039;,&lt;br /&gt;
		&#039;ae&#039;	=&amp;gt;	&#039;æ&#039;,&lt;br /&gt;
		&#039;b&#039;		=&amp;gt;	&#039;β,б&#039;,&lt;br /&gt;
		&#039;c&#039;		=&amp;gt;	&#039;c,ç,ć,ĉ,ċ,č,ћ,ц&#039;,&lt;br /&gt;
		&#039;ch&#039;	=&amp;gt;	&#039;ч&#039;,&lt;br /&gt;
		&#039;d&#039;		=&amp;gt;	&#039;ď,đ,Ð,д,ђ,δ,ð&#039;,&lt;br /&gt;
		&#039;dz&#039;	=&amp;gt;	&#039;џ&#039;,&lt;br /&gt;
		&#039;e&#039;		=&amp;gt;	&#039;e,è,é,ê,ë,ē,ĕ,ė,ę,ě,э,ε,έ&#039;,&lt;br /&gt;
		&#039;f&#039;		=&amp;gt;	&#039;ƒ,ф&#039;,&lt;br /&gt;
		&#039;g&#039;		=&amp;gt;	&#039;ğ,ĝ,ğ,ġ,ģ,г,γ&#039;,&lt;br /&gt;
		&#039;h&#039;		=&amp;gt;	&#039;ĥ,ħ,Ħ,х&#039;,&lt;br /&gt;
		&#039;i&#039;		=&amp;gt;	&#039;i,ì,í,î,ï,ı,ĩ,ī,ĭ,į,и,й,ъ,ы,ь,η,ή&#039;,&lt;br /&gt;
		&#039;ij&#039;	=&amp;gt;	&#039;ĳ&#039;,&lt;br /&gt;
		&#039;j&#039;		=&amp;gt;	&#039;ĵ,j&#039;,&lt;br /&gt;
		&#039;ja&#039;	=&amp;gt;	&#039;я&#039;,&lt;br /&gt;
		&#039;ju&#039;	=&amp;gt;	&#039;яю&#039;,&lt;br /&gt;
		&#039;k&#039;		=&amp;gt;	&#039;ķ,ĸ,κ&#039;,&lt;br /&gt;
		&#039;l&#039;		=&amp;gt;	&#039;ĺ,ļ,ľ,ŀ,ł,л,λ&#039;,&lt;br /&gt;
		&#039;lj&#039;	=&amp;gt;	&#039;љ&#039;,&lt;br /&gt;
		&#039;m&#039;		=&amp;gt;	&#039;μ,м&#039;,&lt;br /&gt;
		&#039;n&#039;		=&amp;gt;	&#039;ñ,ņ,ň,ŉ,ŋ,н,ν&#039;,&lt;br /&gt;
		&#039;nj&#039;	=&amp;gt;	&#039;њ&#039;,&lt;br /&gt;
		&#039;o&#039;		=&amp;gt;	&#039;ò,ó,ô,õ,ø,ō,ŏ,ő,ο,ό,ω,ώ&#039;,&lt;br /&gt;
		&#039;oe&#039;	=&amp;gt;	&#039;œ,ö&#039;,&lt;br /&gt;
		&#039;p&#039;		=&amp;gt;	&#039;п,π&#039;,&lt;br /&gt;
		&#039;ph&#039;	=&amp;gt;	&#039;φ&#039;,&lt;br /&gt;
		&#039;ps&#039;	=&amp;gt;	&#039;ψ&#039;,&lt;br /&gt;
		&#039;r&#039;		=&amp;gt;	&#039;ŕ,ŗ,ř,р,ρ,σ,ς&#039;,&lt;br /&gt;
		&#039;s&#039;		=&amp;gt;	&#039;ş,ś,ŝ,ş,š,с&#039;,&lt;br /&gt;
		&#039;ss&#039;	=&amp;gt;	&#039;ß,ſ&#039;,&lt;br /&gt;
		&#039;sh&#039;	=&amp;gt;	&#039;ш&#039;,&lt;br /&gt;
		&#039;shch&#039;	=&amp;gt;	&#039;щ&#039;,&lt;br /&gt;
		&#039;t&#039;		=&amp;gt;	&#039;ţ,ť,ŧ,τ,т&#039;,&lt;br /&gt;
		&#039;th&#039;	=&amp;gt;	&#039;θ&#039;,&lt;br /&gt;
		&#039;u&#039;		=&amp;gt;	&#039;u,ù,ú,û,ü,ũ,ū,ŭ,ů,ű,ų,у&#039;,&lt;br /&gt;
		&#039;v&#039;		=&amp;gt;	&#039;в&#039;,&lt;br /&gt;
		&#039;w&#039;		=&amp;gt;	&#039;ŵ&#039;,&lt;br /&gt;
		&#039;x&#039;		=&amp;gt;	&#039;χ,ξ&#039;,&lt;br /&gt;
		&#039;y&#039;		=&amp;gt;	&#039;ý,þ,ÿ,ŷ&#039;,&lt;br /&gt;
		&#039;z&#039;		=&amp;gt;	&#039;ź,ż,ž,з,ж,ζ&#039;&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
		foreach( $glyph_array as $letter =&amp;gt; $glyphs ) {&lt;br /&gt;
			$glyphs = explode( &#039;,&#039;, $glyphs );&lt;br /&gt;
			$str = str_replace( $glyphs, $letter, $str );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return $str;&lt;br /&gt;
		}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
=====Example 3 - Custom calendar implemented===== &amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Here is an example of a function to add in the &amp;lt;code&amp;gt;localise.php&amp;lt;/code&amp;gt; file in order to implement a custom calendar for fa-IR (Persian language)&lt;br /&gt;
&amp;lt;/translate&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * @version		$Id: language.php 15628 2010-03-27 05:20:29Z infograf768 $&lt;br /&gt;
 * @copyright	Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.&lt;br /&gt;
 * @copyright	Copyright (C) 2005 - 2014 JoomlaFarsi.com. All rights reserved.&lt;br /&gt;
 * @license		GNU General Public License version 2 or later; see LICENSE.txt&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 jimport(&#039;joomla.utilities.date&#039;);&lt;br /&gt;
abstract class Fa_IRLocalise {&lt;br /&gt;
&lt;br /&gt;
	public static function getPluralSuffixes($count) {&lt;br /&gt;
		if ($count == 0) &lt;br /&gt;
		{&lt;br /&gt;
			$return =  array(&#039;0&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		elseif($count == 1) &lt;br /&gt;
		{&lt;br /&gt;
			$return =  array(&#039;1&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		else &lt;br /&gt;
		{&lt;br /&gt;
			$return = array(&#039;MORE&#039;);&lt;br /&gt;
		}&lt;br /&gt;
		return $return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public static function getIgnoredSearchWords() {&lt;br /&gt;
		$search_ignore = array();&lt;br /&gt;
		$search_ignore[] = &amp;quot;and&amp;quot;;  //change here to fit&lt;br /&gt;
		$search_ignore[] = &amp;quot;in&amp;quot;; //change here to fit&lt;br /&gt;
		$search_ignore[] = &amp;quot;on&amp;quot;; //change here to fit&lt;br /&gt;
		return $search_ignore;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public static function getLowerLimitSearchWord() {&lt;br /&gt;
		return 3;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public static function getUpperLimitSearchWord() {&lt;br /&gt;
		return 20;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public static function getSearchDisplayedCharactersNumber() {&lt;br /&gt;
		return 200;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class fa_IRDate extends JDate {&lt;br /&gt;
	const DAY_NUMBER	= &amp;quot;\x027\x03&amp;quot;;&lt;br /&gt;
	const DAY_NUMBER2	= &amp;quot;\x030\x03&amp;quot;;&lt;br /&gt;
	const DAY_YEAR		= &amp;quot;\x032\x03&amp;quot;;&lt;br /&gt;
	const MONTH_ABBR	= &amp;quot;\x033\x03&amp;quot;;&lt;br /&gt;
	const MONTH_NAME	= &amp;quot;\x034\x03&amp;quot;;&lt;br /&gt;
	const MONTH_NUMBER	= &amp;quot;\x035\x03&amp;quot;;&lt;br /&gt;
	const MONTH_NUMBER2	= &amp;quot;\x036\x03&amp;quot;;&lt;br /&gt;
	const MONTH_LENGTH	= &amp;quot;\x037\x03&amp;quot;;&lt;br /&gt;
	const YEAR_ABBR		= &amp;quot;\x040\x03&amp;quot;;&lt;br /&gt;
	const YEAR_NAME		= &amp;quot;\x041\x03&amp;quot;;&lt;br /&gt;
	const AM_LOWER		= &amp;quot;\x042\x03&amp;quot;;&lt;br /&gt;
	const AM_UPPER		= &amp;quot;\x043\x03&amp;quot;;&lt;br /&gt;
	const PERSIAN_EPOCH	= 1948320.5;&lt;br /&gt;
&lt;br /&gt;
	protected static $month_names	= array(&amp;quot;فروردين&amp;quot;,&amp;quot;ارديبهشت&amp;quot;,&amp;quot;خرداد&amp;quot;,&amp;quot;تیر&amp;quot;,&amp;quot;مرداد&amp;quot;,&amp;quot;شهریور&amp;quot;,&amp;quot;مهر&amp;quot;,&amp;quot;آبان&amp;quot;,&amp;quot;آذر&amp;quot;,&amp;quot;دی&amp;quot;,&amp;quot;بهمن&amp;quot;,&amp;quot;اسفند&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	public function calendar($format, $local = false, $translate = true)&lt;br /&gt;
	{&lt;br /&gt;
		// Do string replacements for date format options that can be translated.&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])d/&#039;, &amp;quot;\\1&amp;quot;.self::DAY_NUMBER2, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])j/&#039;, &amp;quot;\\1&amp;quot;.self::DAY_NUMBER, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])z/&#039;, &amp;quot;\\1&amp;quot;.self::DAY_YEAR, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])M/&#039;, &amp;quot;\\1&amp;quot;.self::MONTH_ABBR, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])F/&#039;, &amp;quot;\\1&amp;quot;.self::MONTH_NAME, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])n/&#039;, &amp;quot;\\1&amp;quot;.self::MONTH_NUMBER, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])m/&#039;, &amp;quot;\\1&amp;quot;.self::MONTH_NUMBER2, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])t/&#039;, &amp;quot;\\1&amp;quot;.self::MONTH_LENGTH, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])y/&#039;, &amp;quot;\\1&amp;quot;.self::YEAR_ABBR, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])Y/&#039;, &amp;quot;\\1&amp;quot;.self::YEAR_NAME, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])a/&#039;, &amp;quot;\\1&amp;quot;.self::AM_LOWER, $format);&lt;br /&gt;
		$format = preg_replace(&#039;/(^|[^\\\])A/&#039;, &amp;quot;\\1&amp;quot;.self::AM_UPPER, $format);&lt;br /&gt;
&lt;br /&gt;
		// Format the date.&lt;br /&gt;
		$return = parent::calendar($format, $local);&lt;br /&gt;
&lt;br /&gt;
		$jd = gregoriantojd($this-&amp;gt;month, $this-&amp;gt;day, $this-&amp;gt;year);&lt;br /&gt;
		$jalaliDate = self::jd_to_persian($jd);&lt;br /&gt;
		$m = $jalaliDate[&#039;mon&#039;];&lt;br /&gt;
		$d = $jalaliDate[&#039;day&#039;];&lt;br /&gt;
		$y = $jalaliDate[&#039;year&#039;];&lt;br /&gt;
&lt;br /&gt;
		// Manually modify the strings in the formated time.&lt;br /&gt;
		if (strpos($return, self::DAY_NUMBER) !== false) {&lt;br /&gt;
			$return = str_replace(self::DAY_NUMBER, $d , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::DAY_NUMBER2) !== false) {&lt;br /&gt;
			$return = str_replace(self::DAY_NUMBER2, sprintf(&amp;quot;%02d&amp;quot;,$d), $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::DAY_YEAR) !== false) {&lt;br /&gt;
			$return = str_replace(self::DAY_YEAR, $jd - self::persian_to_jd(1,1,$y)+1, $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::MONTH_ABBR) !== false) {&lt;br /&gt;
			$return = str_replace(self::MONTH_ABBR, self::$month_names[$m-1] , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::MONTH_NAME) !== false) {&lt;br /&gt;
			$return = str_replace(self::MONTH_NAME, self::$month_names[$m-1] , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::MONTH_NUMBER) !== false) {&lt;br /&gt;
			$return = str_replace(self::MONTH_NUMBER, $m , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::MONTH_NUMBER2) !== false) {&lt;br /&gt;
			$return = str_replace(self::MONTH_NUMBER2, sprintf(&amp;quot;%02d&amp;quot;, $m) , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::MONTH_LENGTH) !== false) {&lt;br /&gt;
			$return = str_replace(self::MONTH_LENGTH, $m &amp;lt; 7 ? 31 : $m &amp;lt; 12 ? 30 : self::leap_persian($y) ? 30 : 29 , $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::YEAR_ABBR) !== false) {&lt;br /&gt;
			$return = str_replace(self::YEAR_ABBR, sprintf(&amp;quot;%02d&amp;quot;,$y % 100), $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::YEAR_NAME) !== false) {&lt;br /&gt;
			$return = str_replace(self::YEAR_NAME, $y, $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::AM_LOWER) !== false) {&lt;br /&gt;
			$return = str_replace(self::AM_LOWER, $this-&amp;gt;format(&#039;a&#039;,$local)==&#039;pm&#039; ? &#039;ب ظ&#039; : &#039;ق ظ&#039;, $return);&lt;br /&gt;
		}&lt;br /&gt;
		if (strpos($return, self::AM_UPPER) !== false) {&lt;br /&gt;
			$return = str_replace(self::AM_UPPER, $this-&amp;gt;format(&#039;a&#039;,$local)==&#039;pm&#039; ? &#039;ب ظ&#039; : &#039;ق ظ&#039;, $return);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		return $return;&lt;br /&gt;
	}&lt;br /&gt;
	public static function jd_to_persian($jd)&lt;br /&gt;
&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		//var $year, $month, $day, $depoch, $cycle, $cyear, $ycycle,&lt;br /&gt;
&lt;br /&gt;
		//    $aux1, $aux2, $yday;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		$jd = floor($jd) + 0.5;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		$depoch = $jd - self::persian_to_jd(1, 1, 475);&lt;br /&gt;
&lt;br /&gt;
		$cycle = floor($depoch / 1029983);&lt;br /&gt;
&lt;br /&gt;
		$cyear = $depoch % 1029983;&lt;br /&gt;
&lt;br /&gt;
		if ($cyear == 1029982) {&lt;br /&gt;
&lt;br /&gt;
		    $ycycle = 2820;&lt;br /&gt;
&lt;br /&gt;
		} else {&lt;br /&gt;
&lt;br /&gt;
		    $aux1 = floor($cyear / 366);&lt;br /&gt;
&lt;br /&gt;
		    $aux2 = $cyear % 366;&lt;br /&gt;
&lt;br /&gt;
		    $ycycle = floor(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) +&lt;br /&gt;
&lt;br /&gt;
		                $aux1 + 1;&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		$year = $ycycle + (2820 * $cycle) + 474;&lt;br /&gt;
&lt;br /&gt;
		if ($year &amp;lt;= 0) {&lt;br /&gt;
&lt;br /&gt;
		    $year--;&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		$yday = ($jd - self::persian_to_jd(1, 1, $year)) + 1;&lt;br /&gt;
&lt;br /&gt;
		$month = ($yday &amp;lt;= 186) ? ceil($yday / 31) : ceil(($yday - 6) / 30);&lt;br /&gt;
&lt;br /&gt;
		$day = ($jd - self::persian_to_jd($month, 1, $year)) + 1;&lt;br /&gt;
&lt;br /&gt;
		return array(&#039;year&#039;=&amp;gt;$year, &#039;mon&#039;=&amp;gt;$month,&#039;day&#039;=&amp;gt; $day);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
	public static function persian_to_jd($month, $day, $year)&lt;br /&gt;
&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		//var $epbase, $epyear;&lt;br /&gt;
&lt;br /&gt;
		$epbase = $year - (($year &amp;gt;= 0) ? 474 : 473);&lt;br /&gt;
&lt;br /&gt;
		$epyear = 474 + $epbase % 2820;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		return $day +&lt;br /&gt;
&lt;br /&gt;
		        (($month &amp;lt;= 7) ?&lt;br /&gt;
&lt;br /&gt;
		            (($month - 1) * 31) :&lt;br /&gt;
&lt;br /&gt;
		            ((($month - 1) * 30) + 6)&lt;br /&gt;
&lt;br /&gt;
		        ) +&lt;br /&gt;
&lt;br /&gt;
		        floor((($epyear * 682) - 110) / 2816) +&lt;br /&gt;
&lt;br /&gt;
		        ($epyear - 1) * 365 +&lt;br /&gt;
&lt;br /&gt;
		        floor($epbase / 2820) * 1029983 +&lt;br /&gt;
&lt;br /&gt;
		        self::PERSIAN_EPOCH;&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	public static function leap_persian($year) {&lt;br /&gt;
&lt;br /&gt;
	    return (((((($year - (($year &amp;gt; 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) &amp;lt; 682;&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Note: One has also to add the right &amp;lt;code&amp;gt;calendar.js&amp;lt;/code&amp;gt; files in the package.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
==The Site-only pack== &amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Concerning those of you providing &amp;quot;site only&amp;quot; packs:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
I.e. IT IS NECESSARY TO PROVIDE AN ADMIN PACK WITH ALL FILES, SOME OF THEM SHOULD BE TRANSLATED and to post a unique package as for a real &amp;quot;full&amp;quot; pack (See above).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
Why? ==&amp;gt; because some plugin ini files are used in front-end! Here is a typical administrator &amp;lt;code&amp;gt;install.xml&amp;lt;/code&amp;gt; in this case. Example for 3.3.x, the files to translate are indicated by =======&amp;gt; :&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;extension version=&amp;quot;3.3&amp;quot; client=&amp;quot;administrator&amp;quot; type=&amp;quot;language&amp;quot; method=&amp;quot;upgrade&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;name&amp;gt;MyLanguage (xx-XX)&amp;lt;/name&amp;gt;&lt;br /&gt;
	&amp;lt;tag&amp;gt;xx-XX&amp;lt;/tag&amp;gt;&lt;br /&gt;
	&amp;lt;version&amp;gt;3.3.3.1&amp;lt;/version&amp;gt;&lt;br /&gt;
	&amp;lt;creationDate&amp;gt;July 2014&amp;lt;/creationDate&amp;gt;&lt;br /&gt;
	&amp;lt;author&amp;gt;MyLanguage translation team : xx-XX Team/author&amp;lt;/author&amp;gt;&lt;br /&gt;
	&amp;lt;authorEmail&amp;gt;traduction@mysite.com&amp;lt;/authorEmail&amp;gt;&lt;br /&gt;
	&amp;lt;authorUrl&amp;gt;http://mysite.com&amp;lt;/authorUrl&amp;gt;&lt;br /&gt;
	&amp;lt;copyright&amp;gt;Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved.&amp;lt;/copyright&amp;gt;&lt;br /&gt;
	&amp;lt;copyright&amp;gt;Copyright (C) date_year - date_year My Team or name. All rights reserved.&amp;lt;/copyright&amp;gt;&lt;br /&gt;
	&amp;lt;license&amp;gt;GNU General Public License version 2 or later; see LICENSE.txt&amp;lt;/license&amp;gt;&lt;br /&gt;
	&amp;lt;description&amp;gt;xx-XX administrator language for 3.3.x&amp;lt;/description&amp;gt;&lt;br /&gt;
	&amp;lt;files&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_admin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_admin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_banners.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_banners.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_ajax.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_ajax.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_cache.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_cache.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_checkin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_checkin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_config.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_config.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_contact.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_contact.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_contenthistory.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_contenthistory.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_cpanel.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_cpanel.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_finder.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_finder.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_installer.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_installer.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_joomlaupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_joomlaupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_languages.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_languages.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_login.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_login.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_mailto.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_media.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_media.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_menus.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_menus.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_messages.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_messages.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_modules.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_modules.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_plugins.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_plugins.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_postinstall.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_postinstall.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_redirect.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_redirect.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_search.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_search.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_templates.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_templates.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_users.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_users.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_wrapper.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.com_wrapper.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.lib_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.localise.php&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_custom.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_custom.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_feed.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_feed.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_latest.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_latest.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_logged.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_logged.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_login.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_login.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_menu.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_menu.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_multilangstatus.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_multilangstatus.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_popular.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_popular.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_quickicon.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_quickicon.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_stats_admin.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_stats_admin.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_status.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_status.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_submenu.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_submenu.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_title.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_title.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_toolbar.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_toolbar.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_version.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.mod_version.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_cookie.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_cookie.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_gmail.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_gmail.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_ldap.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_authentication_ldap.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_captcha_recaptcha.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_captcha_recaptcha.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_emailcloak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_contact.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_contact.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_emailcloak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_finder.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_finder.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_loadmodule.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_loadmodule.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_content_pagebreak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_pagebreak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_pagenavigation.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_pagenavigation.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_content_vote.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_content_vote.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_codemirror.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_codemirror.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_none.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_none.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_tinymce.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors_tinymce.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_article.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_article.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_image.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_image.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_pagebreak.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_pagebreak.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_readmore.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_editors-xtd_readmore.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_extension_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_extension_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_contacts.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_contacts.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_finder_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_finder_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_installer_webinstaller.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_installer_webinstaller.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_quickicon_extensionupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_quickicon_extensionupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_quickicon_joomlaupdate.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_quickicon_joomlaupdate.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_categories.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_categories.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_contacts.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_contacts.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_content.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_content.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_newsfeeds.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_newsfeeds.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_tags.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_tags.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_search_weblinks.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_search_weblinks.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_cache.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_cache.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_debug.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_debug.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_highlight.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_highlight.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_languagecode.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_languagecode.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_languagefilter.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_languagefilter.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_log.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_log.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_logout.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_logout.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_p3p.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_p3p.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_redirect.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_redirect.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_remember.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_remember.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_sef.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_system_sef.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_twofactorauth_totp.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_twofactorauth_totp.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_twofactorauth_yubikey.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_twofactorauth_yubikey.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_user_contactcreator.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_user_contactcreator.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_user_joomla.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_user_joomla.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename&amp;gt;xx-XX.plg_user_profile.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.plg_user_profile.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.tpl_hathor.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.tpl_hathor.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.tpl_isis.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
		&amp;lt;filename&amp;gt;xx-XX.tpl_isis.sys.ini&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename file=&amp;quot;meta&amp;quot;&amp;gt;install.xml&amp;lt;/filename&amp;gt;&lt;br /&gt;
=========&amp;gt;	&amp;lt;filename file=&amp;quot;meta&amp;quot;&amp;gt;xx-XX.xml&amp;lt;/filename&amp;gt;&lt;br /&gt;
	&amp;lt;/files&amp;gt;&lt;br /&gt;
	&amp;lt;params /&amp;gt;&lt;br /&gt;
&amp;lt;/extension&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
For the unstranslated files, just copy the &amp;lt;code&amp;gt;en-GB&amp;lt;/code&amp;gt; ones and change the language prefix.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
==What not to translate== &amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
Don&#039;t translate these lines:&lt;br /&gt;
&lt;br /&gt;
* file &amp;lt;code&amp;gt;fr-FR.ini&amp;lt;/code&amp;gt; = the lines for &amp;lt;code&amp;gt;&amp;quot;JHELP_COMPONENTS_&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
example:&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
JHELP_COMPONENTS_MESSAGING_INBOX=&amp;quot;Components_Messaging_Inbox&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
They are used for mapping the help. When a specific wiki for help per language is available, they will be functional.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Frequent Asked Questions==&lt;br /&gt;
===Why we use .ini files instead of .po .mo===&lt;br /&gt;
INI files were choosen in 2006 for several reasons:&lt;br /&gt;
&lt;br /&gt;
* There was no specific app to deal with .po on all platforms (Poedit was not available on Windows)&lt;br /&gt;
* Anyone, even without any code knowledge, could create/edit an ini file&lt;br /&gt;
* ini files are readable while .po are not&lt;br /&gt;
* You can&#039;t load more than one .pot file per page.&lt;br /&gt;
&lt;br /&gt;
but not only, and this is why it is better to go on:&lt;br /&gt;
&lt;br /&gt;
the following is an example picked from Wordpress of the code in a simple .php file (BTW WP does NOT use any plurals, as I could see in their .po files):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
get_current_screen()-&amp;gt;add_help_tab( array(&lt;br /&gt;
        &#039;id&#039;      =&amp;gt; &#039;publish-box&#039;,&lt;br /&gt;
        &#039;title&#039;   =&amp;gt; __(&#039;Publish Settings&#039;),&lt;br /&gt;
        &#039;content&#039; =&amp;gt; $publish_box,&lt;br /&gt;
    ) );&lt;br /&gt;
&lt;br /&gt;
    $discussion_settings  = &#039;&amp;lt;p&amp;gt;&#039; . __(&#039;&amp;lt;strong&amp;gt;Send Trackbacks&amp;lt;/strong&amp;gt; - Trackbacks are a way to notify legacy blog systems that you&amp;amp;#8217;ve linked to them. Enter the URL(s) you want to send trackbacks. If you link to other WordPress sites they&amp;amp;#8217;ll be notified automatically using pingbacks, and this field is unnecessary.&#039;) . &#039;&amp;lt;/p&amp;gt;&#039;;&lt;br /&gt;
    $discussion_settings .= &#039;&amp;lt;p&amp;gt;&#039; . __(&#039;&amp;lt;strong&amp;gt;Discussion&amp;lt;/strong&amp;gt; - You can turn comments and pings on or off, and if there are comments on the post, you can see them here and moderate them.&#039;) . &#039;&amp;lt;/p&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
    get_current_screen()-&amp;gt;add_help_tab( array(&lt;br /&gt;
        &#039;id&#039;      =&amp;gt; &#039;discussion-settings&#039;,&lt;br /&gt;
        &#039;title&#039;   =&amp;gt; __(&#039;Discussion Settings&#039;),&lt;br /&gt;
        &#039;content&#039; =&amp;gt; $discussion_settings,&lt;br /&gt;
    ) );&lt;br /&gt;
} elseif ( &#039;page&#039; == $post_type ) {&lt;br /&gt;
    $page_attributes = &#039;&amp;lt;p&amp;gt;&#039; . __(&#039;&amp;lt;strong&amp;gt;Parent&amp;lt;/strong&amp;gt; - You can arrange your pages in hierarchies. For example, you could have an &amp;amp;#8220;About&amp;amp;#8221; page that has &amp;amp;#8220;Life Story&amp;amp;#8221; and &amp;amp;#8220;My Dog&amp;amp;#8221; pages under it. There are no limits to how many levels you can nest pages.&#039;) . &#039;&amp;lt;/p&amp;gt;&#039; .&lt;br /&gt;
        &#039;&amp;lt;p&amp;gt;&#039; . __(&#039;&amp;lt;strong&amp;gt;Template&amp;lt;/strong&amp;gt; - Some themes have custom templates you can use for certain pages that might have additional features or custom layouts. If so, you&amp;amp;#8217;ll see them in this dropdown menu.&#039;) . &#039;&amp;lt;/p&amp;gt;&#039; .&lt;br /&gt;
        &#039;&amp;lt;p&amp;gt;&#039; . __(&#039;&amp;lt;strong&amp;gt;Order&amp;lt;/strong&amp;gt; - Pages are usually ordered alphabetically, but you can choose your own order by entering a number (1 for first, etc.) in this field.&#039;) . &#039;&amp;lt;/p&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
    get_current_screen()-&amp;gt;add_help_tab( array(&lt;br /&gt;
        &#039;id&#039; =&amp;gt; &#039;page-attributes&#039;,&lt;br /&gt;
        &#039;title&#039; =&amp;gt; __(&#039;Page Attributes&#039;),&lt;br /&gt;
        &#039;content&#039; =&amp;gt; $page_attributes,&lt;br /&gt;
    ) );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This for GetText:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
__(&#039;&amp;lt;strong&amp;gt;Parent&amp;lt;/strong&amp;gt; - You can arrange your pages in hierarchies. For example, you could have an &amp;amp;#8220;About&amp;amp;#8221; page that has &amp;amp;#8220;Life Story&amp;amp;#8221; and &amp;amp;#8220;My Dog&amp;amp;#8221; pages under it. There are no limits to how many levels you can nest pages.&#039;) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is simpler with ini files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
JText::_(&amp;quot;SOME_CONSTANT&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Working with plurals===&lt;br /&gt;
Some languages like Russian do NOT have the same plurals as English. They need to add strins to fit their definitions. Joomla CMS provides a solution for it and it can be seen in the file localise.php added to the language package. For example:&lt;br /&gt;
&lt;br /&gt;
Concerning plurals, this is the Russian plural:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
public static function getPluralSuffixes($count)&lt;br /&gt;
    {&lt;br /&gt;
        if ($count == 0) {&lt;br /&gt;
            $return = array(&#039;0&#039;);&lt;br /&gt;
        } else {&lt;br /&gt;
            $return = array(($count%10==1 &amp;amp;&amp;amp; $count%100!=11 ? &#039;1&#039; : ($count%10&amp;gt;=2 &amp;amp;&amp;amp; $count%10&amp;lt;=4 &amp;amp;&amp;amp; ($count%100&amp;lt;10 || $count%100&amp;gt;=20) ? &#039;2&#039; : &#039;MORE&#039;)));&lt;br /&gt;
        }&lt;br /&gt;
        return $return;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An this is the Scottish gaelic one&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
public static function getPluralSuffixes($count) {&lt;br /&gt;
        if ($count == 0 || $count &amp;gt; 19) {&lt;br /&gt;
            $return =  array(&#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        elseif($count == 1 || $count == 11) {&lt;br /&gt;
               $return =  array(&#039;1&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        elseif($count == 2 || $count == 12) {&lt;br /&gt;
               $return =  array(&#039;2&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        elseif(($count &amp;gt; 2 &amp;amp;&amp;amp; $count &amp;lt; 12) || ($count &amp;gt; 12 &amp;amp;&amp;amp; $count &amp;lt; 19)) {&lt;br /&gt;
                $return =  array(&#039;FEW&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        return $return;&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now compare with en-GB:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
public static function getPluralSuffixes($count) {&lt;br /&gt;
        if ($count == 0) {&lt;br /&gt;
            $return =  array(&#039;0&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        elseif($count == 1) {&lt;br /&gt;
            $return =  array(&#039;1&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            $return = array(&#039;MORE&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        return $return;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means that when we have in en-GB:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_0=&amp;quot;No banner successfully checked in&amp;quot;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_1=&amp;quot;%d banner successfully checked in&amp;quot;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_MORE=&amp;quot;%d banners successfully checked in&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Russian they need:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_0=&amp;quot;Ни один баннер не был разблокирован&amp;quot;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_1=&amp;quot;%d баннер успешно разблокирован&amp;quot;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_2=&amp;quot;%d баннера успешно разблокировано&amp;quot;&lt;br /&gt;
COM_BANNERS_BANNERS_N_ITEMS_CHECKED_IN_MORE=&amp;quot;%d баннеров успешно разблокировано&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Standard ISO codes for naming language packages===&lt;br /&gt;
The official link concerning Country codes is: https://www.iso.org/obp/ui/#search&lt;br /&gt;
&lt;br /&gt;
Joomla uses alpha-2 codes:&lt;br /&gt;
&lt;br /&gt;
CS was the official country code of Tchecoslovakia BEFORE it was separated into the Czeck Republic (CZ) and Slovakia(SK)&lt;br /&gt;
&lt;br /&gt;
Our Lang tags are composed of 2 parts:&lt;br /&gt;
&lt;br /&gt;
* the languagecode&lt;br /&gt;
* the countrycode&lt;br /&gt;
&lt;br /&gt;
Here is the official list for language code: http://www.iso.org/iso/home/standards/language_codes.htm&lt;br /&gt;
&lt;br /&gt;
When possible we use the 2 letters language code, otherwise we use 3. For example we have for Joomla&lt;br /&gt;
&lt;br /&gt;
ckb-IQ for Kurdish Sorani&lt;br /&gt;
&lt;br /&gt;
srp-ME for Montenegrin&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
[[Category:Joomla! 3.0]]&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
[[Category:Language Development]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=User_talk:Javiparati&amp;diff=205148</id>
		<title>User talk:Javiparati</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=User_talk:Javiparati&amp;diff=205148"/>
		<updated>2015-07-13T08:33:46Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Translation Tags. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Translation Tags. ==&lt;br /&gt;
&lt;br /&gt;
Bonjour Javier,&amp;lt;br /&amp;gt;&lt;br /&gt;
I hope everything goes well for you.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing with tagging for translation is that the # for the section is generated automaticly then in fact (I think this is what you did with your text the right way) you just need to add the tags &amp;lt;nowiki&amp;gt;&amp;amp;lt;translate&amp;gt;Text to translate&amp;amp;lt;/translate&amp;gt;&amp;lt;/nowiki&amp;gt;. Here, the &amp;lt;nowiki&amp;gt;&amp;amp;lt;!--T:27--&amp;gt;&amp;lt;/nowiki&amp;gt; will/has been generated by the system.&amp;lt;br /&amp;gt;&lt;br /&gt;
But, at this point, if there&#039;s no prob for you, I&#039;d prefer to tag/mark for translation myself for the proper management of my workflow.&amp;lt;br /&amp;gt;&lt;br /&gt;
Just add your changes on the page then I will be notified + usually I tag/mark/translate (in FR ;) ) the same day max.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a &#039;&#039;&#039;new&#039;&#039;&#039; page to be translated, please follw: &amp;lt;br /&amp;gt;&lt;br /&gt;
https://docs.joomla.org/Category:Needs_to_be_marked_for_translation&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Thanks for your help,&amp;lt;br /&amp;gt;&lt;br /&gt;
([[User:MATsxm|MATsxm]] ([[User talk:MATsxm|talk]]) 08:59, 12 July 2015 (CDT))&lt;br /&gt;
&lt;br /&gt;
:Hi Javier&lt;br /&gt;
&lt;br /&gt;
:I added back in the new &amp;quot;test&amp;quot; @[[User:MATsxm|MATsxm]] explained it well. Just worry about the content though, not the tags. You can add them in, but MAT will know if the page&#039;s content changes and can add the tags. Anything with a &amp;amp;lt;!-- #number --&amp;gt; is added by the system when the content changes are approved.&lt;br /&gt;
&lt;br /&gt;
::[[User:Tom Hutchison|Tom Hutchison]] ([[User talk:Tom Hutchison|talk]]) 11:31, 12 July 2015 (CDT)&lt;br /&gt;
&lt;br /&gt;
Ok. Thanks ^_^&lt;br /&gt;
&lt;br /&gt;
[[User:Javiparati|Javier Gómez]] ([[User talk:Javiparati|talk]]) 03:33, 13 July 2015 (CDT)&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Joomla:Commit_Guidelines&amp;diff=205107</id>
		<title>Joomla:Commit Guidelines</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Joomla:Commit_Guidelines&amp;diff=205107"/>
		<updated>2015-07-12T11:48:01Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: Tom have I setted well the Tranlsation tag?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&amp;lt;languages /&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
Commit Guidelines for the Joomla! CMS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
These guidelines are not meant to be strict rules, but a guide for what we consider best practice.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;== Merge-Commit vs Squashing == &amp;lt;!--T:2--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Merge-Commit === &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
When you click the “Merge” button on GitHub, it will create a merge-commit named “Merge pull request #1234 from User/Branch”. This commit will show together with all commits in the PR in the log. Each commit will have the original date when it was created, not when it was actually merged. While this is nice to preserve the actual commit history and is fine with Git Clients which show the branches, it becomes unreadable especially on the GitHub log page.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Squashing === &amp;lt;!--T:4--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When you squash the commits, you create a single commit consisting of all original commits. This single commit is then pushed to master and can be named in a standardised way.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Recommendation === &amp;lt;!--T:6--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
We recommend to squash the commits in most cases. The “Merge” button in GitHub should only be used for simple PRs with only a few commits and when it’s only a few days old. Most of time, this is the case for simple PRs dealing with codestyle or language strings.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;== Naming Conventions == &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
When squashing commits, one should follow these naming conventions so the log will become easier to read.&amp;lt;/translate&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Format === &amp;lt;!--T:9--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;[Prefix]&amp;gt; &amp;lt;Title&amp;gt;. &amp;lt;Issue&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;&#039;&#039;Description&#039;&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Prefixes === &amp;lt;!--T:10--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&amp;lt;translate&amp;gt;&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
Prefix&amp;lt;/translate&amp;gt;&lt;br /&gt;
!&amp;lt;translate&amp;gt;&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Meaning&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|sec&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
Security&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|bug&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
Bug fix&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Add&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|rem&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
Remove&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lang&lt;br /&gt;
|Language&lt;br /&gt;
|-&lt;br /&gt;
|doc&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Documentation / Notes&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|imp&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Improvement&amp;lt;/translate&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|tests&lt;br /&gt;
|&amp;lt;translate&amp;gt;&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
Tests&amp;lt;/translate&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
A commit may have multiple prefixes. If that’s the case, each goes into its own brackets.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Title === &amp;lt;!--T:20--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
Use a descriptive title for the commit. Usually the title of the PR will be fine.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Issue === &amp;lt;!--T:22--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
After the title we add a dot, followed by a text like “Closes #1234”. This will automatically close the PR when the commit is pushed to staging and also provides a link to the PR. See https://help.github.com/articles/closing-issues-via-commit-messages for the available keywords.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Description === &amp;lt;!--T:24--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
The description is optional. It can contain additional information to the commit. Usually that is not needed as the information is available in the linked Pull Request.&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;translate&amp;gt;=== Example === &amp;lt;!--T:26--&amp;gt;&amp;lt;/translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[lng] Clarify content smart search plugins. Closes #1833&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
[[Category:CMS Development Reference]]&lt;br /&gt;
[[Category:CMS Maintainers]]&lt;br /&gt;
[[Category:Guidelines]]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188678</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188678"/>
		<updated>2015-06-04T07:44:08Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* What is Codeception? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
=== Types of tests ===&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however &#039;&#039;&#039;this page is focused in System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;System testing&#039;&#039;&#039; uses a production-like environment to verify the system as a whole, including user interfaces, databases, web servers, logging, etc. &lt;br /&gt;
&lt;br /&gt;
- A &#039;&#039;&#039;unit test&#039;&#039;&#039; verifies a single behavior of a single unit – this can be a function, a method, or a class. A logical unit is something that can be reasoned about in isolation. The unit must be completely under your control. The test should limit the number of other units it touches on, and should not touch any part outside of your own system. As such, the test should only fail for one reason.&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Integration testing&#039;&#039;&#039; means we’re verifying that that different units are working together. It focuses on the interfaces between components. Some of these components may be from third parties. When they break, they signal that, although individual units may behave correctly, something changed in the API that caused failure in another place. Often, integration tests are slower than unit tests.&lt;br /&gt;
&lt;br /&gt;
As mentioned at the beginning of this text, the current page is focused on &#039;&#039;&#039;System Tests&#039;&#039;&#039; and more specifically using Webdriver. The reason is that we came to the conclusion that this type of tests combined with the already existing Unit tests in Joomla are the most successful way to test our current code.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;30&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 30 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
A waitForText over 10 seconds will definitely mean that something is not performing well. Maybe a non strict Locator is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188228</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188228"/>
		<updated>2015-06-03T11:05:33Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: fix typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;30&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 30 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
A waitForText over 10 seconds will definitely mean that something is not performing well. Maybe a non strict Locator is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Complex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188227</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=188227"/>
		<updated>2015-06-03T11:03:08Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* How much time should I wait for an Element or Text? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;,&#039;30&#039;,[&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. &#039;&#039;&#039;We suggest to set it for 30 seconds&#039;&#039;&#039;, because running the tests in slow computers can easily get to that time in some tasks. &lt;br /&gt;
&lt;br /&gt;
A waitForText over 10 seconds will definitely mean that something is not performing well. Maybe a non strict Locator is being used and Selenium takes to much time to find the element. However we have even identified cases were some steps take longer than 30 seconds in very slow computers, specifically installing joomla, see https://github.com/joomla-projects/joomla-browser/commit/b70f195140e599649cf98f051d7a31388c4f1632. For this cases we can&#039;t do much, other than recommend to add more memory to the local web server.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186800</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186800"/>
		<updated>2015-05-31T12:33:29Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Getting started from scratch: what you need to download and install */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; no matter if you are executing [https://github.com/joomla/joomla-cms/tree/staging/tests/codeception#testing-joomla-cms Joomla CMS Tests], [https://github.com/joomla-extensions/weblinks#tests Weblinks], or tests in other Joomla extensions, in any case you are asked to fork the repository into your local machine under your htdocs folder of your local web-server. The reason is that, the automated scripts that launches the tests use the repository files for the tests.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with setting up a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, [&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186789</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186789"/>
		<updated>2015-05-31T12:27:18Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: remove the need for wget since is not anymore needed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Very important:&#039;&#039;&#039; The downloaded GIT directory must be inside your htdocs folder of your local web-server. Otherwise the test will not work! The files from the &#039;weblinks&#039; folder must be loadable via your local web-server with your browser.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, [&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186788</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=186788"/>
		<updated>2015-05-31T12:26:49Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: remove the need for Wget&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Getting started from scratch: what you need to download and install ==&lt;br /&gt;
To get the test environment running you need to have several components installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Very important:&#039;&#039;&#039; The downloaded GIT directory must be inside your htdocs folder of your local web-server. Otherwise the test will not work! The files from the &#039;weblinks&#039; folder must be loadable via your local web-server with your browser.&lt;br /&gt;
&lt;br /&gt;
=== local webserver ===&lt;br /&gt;
If you do not already have a local test server running you may want to check out:&lt;br /&gt;
https://www.mamp.info/&lt;br /&gt;
https://www.apachefriends.org/&lt;br /&gt;
http://www.ampps.com/&lt;br /&gt;
&lt;br /&gt;
If you are not familiar with a local web-server, learn that first before you advance futher. &lt;br /&gt;
&lt;br /&gt;
====Wget on Mac====&lt;br /&gt;
For Mac Users Homebrew (package manager for OS X) is a very easy way to get wget running. Download Homebrew at: http://brew.sh/ &lt;br /&gt;
After installation run the following command in your terminal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
brew install wget&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Java Runtime Environment (JRE) ===&lt;br /&gt;
The JRE has to be installed, so the tests will be executable. You find the recent versions at the Oracle Website.&lt;br /&gt;
In end of May 2015 this is: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&lt;br /&gt;
later on that link could be obsolete and should be changed if there is a newer version out.&lt;br /&gt;
&lt;br /&gt;
Newer Mac OS Versions are not shipped any more with the JRE, so they have to download that too.&lt;br /&gt;
&lt;br /&gt;
=== Firefox ===&lt;br /&gt;
Selenium is testing in the browser Firefox. The selenium version is not that quick with the updates, as the Firefox browser, if the test is not executable, then it can be that you manually have to install an older version of Firefox.&lt;br /&gt;
Sadly that can be a try and error thing. To get older versions of Firefox: https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/ here you will find many folders. Just try the first one that came before the Firefox version that you have been using (and that did not work). In the version folders you will find folders for all the different operating systems.&lt;br /&gt;
&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
=== configure test system variables ===&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance.suite.dist.yml rename.png|thumbnail|left|Screenshot of file structure]]&lt;br /&gt;
&lt;br /&gt;
In your the folder that you installed, downloaded, pulled (git) the project, you have to rename the &amp;quot;&#039;&#039;acceptance.suite.dist.yml&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;acceptance.suite.yml&#039;&#039;&amp;quot; and configure the parameters to your system variables.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
   config:&lt;br /&gt;
        JoomlaBrowser:&lt;br /&gt;
            url: &#039;http://localhost/tests/joomla-cms3&#039;&lt;br /&gt;
            # the url that points to the joomla installation at /tests/system/joomla-cms&lt;br /&gt;
            browser: &#039;firefox&#039;&lt;br /&gt;
            window_size: 1024x768&lt;br /&gt;
    [...]&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:Run Command vendor bin robo test-acceptance.png|thumbnail|test:acceptance]]&lt;br /&gt;
Once your machine is able to run tests (see &#039;&#039;The Joomla Browser Module&#039;&#039;), you are able to start working.&lt;br /&gt;
&lt;br /&gt;
Check the contents of the /tests/ folder in weblinks and try to understand the structure of the tests.&lt;br /&gt;
For each function you have a directory and sometimes a configuration file, both will have the corresponding name.&lt;br /&gt;
* FunctionName.yml - these files contain configurations for the function folders&lt;br /&gt;
* FunctionName - contains the &#039;&#039;FunctionName&#039;&#039; test&lt;br /&gt;
* joomla-cms3 - contains the latest Joomla! installation&lt;br /&gt;
&lt;br /&gt;
After that check the tasks are at: https://github.com/joomla-extensions/weblinks/issues/47&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, [&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=183687</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=183687"/>
		<updated>2015-05-25T11:09:03Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Always add xPath locators to your tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add Strict Locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, [&#039;id&#039; =&amp;gt; &#039;messages&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, [&#039;css&#039; =&amp;gt; &#039;h3&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert&#039;]);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, [&#039;class&#039; =&amp;gt; &#039;alert-success&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, [&#039;...&#039; =&amp;gt; &#039;...&#039;]);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=183682</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=183682"/>
		<updated>2015-05-25T11:00:56Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we give priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
Still there is a definitive method of using locators that made them readable and performant called: strict Locators see [[Testing_Joomla_Extensions_with_Codeception#Writting_reliable_locators]].&lt;br /&gt;
&lt;br /&gt;
With them we do: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField([&#039;id&#039; =&amp;gt; &#039;username_field&#039;], &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=178440</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=178440"/>
		<updated>2015-05-05T10:20:32Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Best Practices at Testing */ adding best practices for Locators&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== Writting reliable locators ===&lt;br /&gt;
Writing good locators can be tricky. The Mozilla team has written an excellent guide titled [https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/ Writing reliable locators for Selenium and WebDriver tests].&lt;br /&gt;
&lt;br /&gt;
If the locator is an array, it should have a single element, with the key signifying the locator type (`id`, `name`, `css`, `xpath`, `link`, or `class`) and the value being the locator itself. This is called a &amp;quot;strict&amp;quot; locator. Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* [&#039;id&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div id=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;name&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div name=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;css&#039; =&amp;gt; &#039;input[type=input][value=foo]&#039;] matches `&amp;lt;input type=&amp;quot;input&amp;quot; value=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;xpath&#039; =&amp;gt; &amp;quot;//input[@type=&#039;submit&#039;][contains(@value, &#039;foo&#039;)]&amp;quot;] matches `&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;foobar&amp;quot;&amp;gt;`&lt;br /&gt;
* [&#039;link&#039; =&amp;gt; &#039;Click here&#039;] matches `&amp;lt;a href=&amp;quot;google.com&amp;quot;&amp;gt;Click here&amp;lt;/a&amp;gt;`&lt;br /&gt;
* [&#039;class&#039; =&amp;gt; &#039;foo&#039;] matches `&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=175521</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=175521"/>
		<updated>2015-04-23T11:15:01Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* The principles for writing a test: Readability and Performance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=175520</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=175520"/>
		<updated>2015-04-23T11:14:06Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: Add Joomla Browser info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
=== The Joomla Browser Module ===&lt;br /&gt;
The Joomla Browser is a Codeception Module that incorporates general functions to your tests like:&lt;br /&gt;
- do administrator login&lt;br /&gt;
- install joomla&lt;br /&gt;
- install extension&lt;br /&gt;
- ...&lt;br /&gt;
&lt;br /&gt;
Find details about it at: https://github.com/joomla-projects/joomla-browser#table-of-contents&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171195</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171195"/>
		<updated>2015-04-10T09:25:25Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Don&amp;#039;t use double quotes, use single quotes instead */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The reason of not being able to use double quotes is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;br /&gt;
&lt;br /&gt;
===Do not leave spaces between parameters in Cepts===&lt;br /&gt;
See the two lines:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
// Good&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;,10,&#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Main Configuration&#039;,&amp;quot; 10&amp;quot;,&amp;quot; &#039;h3&#039;&lt;br /&gt;
&lt;br /&gt;
The reason that you are asked to not add spaces between parameters is due to a bug in Codeception humanize funtions, see issue: https://github.com/Codeception/Codeception/issues/1847&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171194</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171194"/>
		<updated>2015-04-10T08:45:17Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you [[Testing_Joomla_Extensions_with_Codeception#Generating_txt.2Fhtml_scenarios|generate the scenarios]] you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171193</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=171193"/>
		<updated>2015-04-10T08:44:20Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Generating txt/html scenarios===&lt;br /&gt;
Codeception allows you to generate user-friendly text scenarios from scenario-driven from Cest and Cept php test (see http://codeception.com/docs/reference/Commands#GenerateScenarios).&lt;br /&gt;
&lt;br /&gt;
===Don&#039;t use double quotes, use single quotes instead===&lt;br /&gt;
Do not use double quotes (&amp;quot;) for surrounding strings:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do, when you generate the scenarios you will get this bad result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &amp;quot;&amp;quot;Congratulations! Joomla! is now installed.&amp;quot;&amp;quot;,&amp;quot; 30&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If you use single quotes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Congratulations! Joomla! is now installed.&#039;, 30);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get the right expected result:&lt;br /&gt;
&lt;br /&gt;
 I wait for text &#039;Congratulations! Joomla! is now installed.&#039;,&amp;quot; 30&amp;quot;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168821</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168821"/>
		<updated>2015-04-02T09:43:49Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* How much time should I wait for an Element or Text? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
==== How much time should I wait for an Element or Text? ====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168820</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168820"/>
		<updated>2015-04-02T09:43:30Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Using locators in $I-&amp;gt;waitForText */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
===== How much time should I wait for an Element or Text? =====&lt;br /&gt;
You may have noticed that the second parameter in the I waitForText is an integer that represents how much &amp;quot;time to wait&amp;quot; in seconds:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;a text to wait for&#039;, 10, .locator);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168809</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=168809"/>
		<updated>2015-04-02T07:37:02Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Using locators in $I-&amp;gt;waitForText */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
Run Selenium server&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download&lt;br /&gt;
curl -O http://selenium-release.storage.googleapis.com/2.45/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&lt;br /&gt;
# And start the Selenium Server&lt;br /&gt;
java -Xms40m -Xmx256m -jar /Applications/XAMPP/xamppfiles/htdocs/selenium/selenium-server-standalone-2.45.0.jar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incase of an element has multiple css classes, When Using CSS Locators make sure you use more specific class as locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Item Succesfully Created&#039;, 10, &#039;.alert-success&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A page could have mutiple elements which can have &#039;&#039;alert&#039;&#039; css class associated, hence being more specific helps.&lt;br /&gt;
&lt;br /&gt;
===== Using locators in $I-&amp;gt;waitForText =====&lt;br /&gt;
You may have noticed that the second parameter in the I wait for text is the &amp;quot;time to wait&amp;quot; in seconds. But, how much time is the right time to wait for a text?&lt;br /&gt;
&lt;br /&gt;
PHP maximum execution time before returning a Fatal Error for timeout is set by default to 30 seconds. We suggest to set it for 10 seconds. A waitForText over 10 seconds will definitely mean that something is not performing well.&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166769</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166769"/>
		<updated>2015-03-27T11:37:04Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Best Practices at Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working with Hidden Elements ===&lt;br /&gt;
Selenium can&#039;t interact with elements that are not visible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;http://www.joomla.org&amp;quot; style=&amp;quot;display: none;&amp;quot; id=&amp;quot;joomla_site&amp;quot;&amp;gt;go to joomla&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case you can&#039;t do:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually this happens when you need to wait for a Javascript animation that end up showing that element, so in this case you will need to do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;waitForElementVisible(&#039;#joomla_site&#039;);&lt;br /&gt;
$I-&amp;gt;click(&#039;go to joomla&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166768</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166768"/>
		<updated>2015-03-27T11:26:56Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* The principles for writing a test: Readability and Performance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
Note: sometimes this tricks are not always possible, labels are not always there or there are some elements hidden that shows and hides depending on a Javascript. All these special cases would require a Page element.&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166767</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166767"/>
		<updated>2015-03-27T11:25:24Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* The principles for writing a test: Readability and Performance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166766</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166766"/>
		<updated>2015-03-27T11:24:56Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* The principles for writing a test: Readability and Performance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performance hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166765</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166765"/>
		<updated>2015-03-27T11:21:21Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* The principles for writing a test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test: Readability and Performance ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performant hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166764</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166764"/>
		<updated>2015-03-27T11:20:46Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Structure of a test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Architecture of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The principles for writing a test ==&lt;br /&gt;
In Joomla we wive priority to Readability over Performance, even when performance is a must.&lt;br /&gt;
&lt;br /&gt;
To explain that let me show an example: Let&#039;s say that we want to fill a field Username in a login form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;form action=&amp;quot;administrator/index.php&amp;quot; method=&amp;quot;post&amp;quot; id=&amp;quot;form-login&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;label for=&amp;quot;username_field&amp;quot;&amp;gt;Username&amp;lt;/label&amp;gt;&lt;br /&gt;
  &amp;lt;input name=&amp;quot;username_field&amp;quot; tabindex=&amp;quot;1&amp;quot; id=&amp;quot;username_field&amp;quot; type=&amp;quot;text&amp;quot; size=&amp;quot;15&amp;quot; /&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the most performant way to fill that form field would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;#username_field&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And usually we would move that to a page object element ending in:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(\LoginPage::$username, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However Codeception is a smart framework and it adds some magic to it&#039;s methods (see: https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/WebDriver.php#L511-L513). It allows me to write more readable tests (keeping performant hight). &lt;br /&gt;
&lt;br /&gt;
If we do this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;fillField(&#039;username&#039;, &#039;Mark&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Codeception will be smart and will search first in the page if there is any &amp;quot;LABEL&amp;quot; called Username. That is a fast operation, so performance will be affected just a little. And instead we have written less code than in previous examples.&lt;br /&gt;
&lt;br /&gt;
In conclusion we have more readable tests and less code to maintain while keeping performance. That is a win!&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166763</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166763"/>
		<updated>2015-03-27T11:02:40Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* How to use URLs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead of hardcoding the url in the test:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The pros of this approach is:&lt;br /&gt;
- first way is more readable for non developers. &lt;br /&gt;
- it helps to make tests more maintenable in the case of a url change in the system&lt;br /&gt;
&lt;br /&gt;
However in joomla a change in an url is rare, and if it happens changing it will just be a Find&amp;amp;Replace task. I Joomla test we want to have the benefit of both, the url and a representative name that describes the page where we are going. That will make our tests more readable. Thus, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166762</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166762"/>
		<updated>2015-03-27T10:59:52Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* How to use URLs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Codeception documentation suggests to use URL&#039;s as properties of a Page Object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has sense because for readability sometimes you would prefer to see:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaAdministratorNewBannerPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The first way is more readable for non developers. To have the benefit of both, the url and a representative name that describes the page where we are going, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166761</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=166761"/>
		<updated>2015-03-27T10:58:37Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Best Practices at Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== How to use URLs ===&lt;br /&gt;
Is common in Codeception documentation to see URL&#039;s as properties of a page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaInstallationConfigurationPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has sense because for readability sometimes you would prefer to see:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(JoomlaAdministratorNewBannerPage::$URL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The first way is more readable for non developers. To have the benefit of both, the url and a representative name that describes the page where we are going, we will write the urls the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;amGoingTo(&#039;go to Create New Banner page at Joomla Administrator&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;/administrator/index.php?option=com_banners&amp;amp;view...&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161289</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161289"/>
		<updated>2015-03-03T19:31:27Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* What is Codeception? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: &lt;br /&gt;
&lt;br /&gt;
{{#widget:YouTube|id=Vc1BJNnhsFM}}&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161288</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161288"/>
		<updated>2015-03-03T19:28:06Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* What is Codeception? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
See the following video of codeception in action testing Joomla: https://www.youtube.com/watch?v=Vc1BJNnhsFM&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161270</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161270"/>
		<updated>2015-03-03T19:08:32Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Quote and Double Quotes in Compex XPaths */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page object]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161269</id>
		<title>Testing Joomla Extensions with Codeception</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=Testing_Joomla_Extensions_with_Codeception&amp;diff=161269"/>
		<updated>2015-03-03T19:08:00Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: /* Quote and Double Quotes in Compex XPaths */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;Note: this page is under construction&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is Codeception? ==&lt;br /&gt;
Codeception PHP Testing Framework is designed to work just out of the box. This means its installation requires minimal steps and no external dependencies preinstalled (except PHP, of course). Only one configuration step should be taken and you are ready to test your web application from an eye of actual user.&lt;br /&gt;
&lt;br /&gt;
Codeception provides possibilities to do Unit Testing or to Test APIs, however this page is focused in &#039;&#039;&#039;System Testing&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Why Use Codeception? ==&lt;br /&gt;
&#039;&#039;Why use Codeception when we already have Selenium IDE?&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Codeception works great with Selenium. But with Codeception you can write your tests in PHP. The main reason is: Selenium IDE tests are tightly bound to XPath locators. If you ever change anything in layout tests will fall. Codeception locators are more stable. You can use names, labels, button names and CSS to match elements on page. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Selenium WebDriver integration&lt;br /&gt;
* Elements matched by name, CSS, XPath&lt;br /&gt;
* PageObjects and StepObjects included&lt;br /&gt;
* Powered by PHPUnit&lt;br /&gt;
* Data Cleanup&lt;br /&gt;
* Parallel Execution of tests&lt;br /&gt;
* BDD-style readable tests&lt;br /&gt;
&lt;br /&gt;
== Structure of a test ==&lt;br /&gt;
The testing framework is built on the three layered testing architecture&lt;br /&gt;
&lt;br /&gt;
=== Scenarios (Cept Class) ===&lt;br /&gt;
Cept or Test, it is the main class which contains steps of execution for the tests, Cept Class will call Step Class functions which will indirectly make use of page objects to perform operations&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I = new AcceptanceTester($scenario);&lt;br /&gt;
$I-&amp;gt;wantTo(&#039;Install Joomla CMS&#039;);&lt;br /&gt;
$I-&amp;gt;amOnPage(&#039;http://localhost/installation/index.php&#039;);&lt;br /&gt;
// I Wait for the text Main Configuration, meaning that the page is loaded&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Main Configuration&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;Language Selector&#039;]);&lt;br /&gt;
$I-&amp;gt;click(JoomlaInstallationConfigurationPage::$elements[&#039;English (United Kingdom)&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Site Name&#039;, &#039;weblinks&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Description&#039;, &#039;Site for testing Weblinks component&#039;);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Email&#039;, $cfg[&#039;Admin email&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Username&#039;, $cfg[&#039;username&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;fillField(&#039;Confirm Admin Password&#039;, $cfg[&#039;password&#039;]);&lt;br /&gt;
$I-&amp;gt;click(&#039;Next&#039;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Page Objects ===&lt;br /&gt;
Each page on your application has a class which we call page objects, each page class will have information about the URL, fields, Text present on the page. We use the best possible selector for any field on the page.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginManagerPage&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * @var string Url of the page&lt;br /&gt;
	 */&lt;br /&gt;
	public static $URL = &#039;/administrator/index.php&#039;;&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * Array of Page elements indexed by descriptive name or label&lt;br /&gt;
	 *&lt;br /&gt;
	 * @var array&lt;br /&gt;
	 */&lt;br /&gt;
	public static $elements = array(&lt;br /&gt;
		&#039;username&#039; =&amp;gt; &amp;quot;#mod-login-username&amp;quot;,&lt;br /&gt;
		&#039;password&#039; =&amp;gt; &amp;quot;#mod-login-password&amp;quot;&lt;br /&gt;
	);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming convention for Page Objects ====&lt;br /&gt;
When this document is created Codeception 2.0 was not having a PSR-4 compatible autoloader. Therefore we are creating a convention so with the future Codeception 2.1 with PSR-4 compatible autoloader (https://github.com/Codeception/Codeception/pull/1228) we are creating a naming convention for Pages so it will cost us a small effort to move to autoloaded classes in the future.&lt;br /&gt;
&lt;br /&gt;
The naming convention works as follows:&lt;br /&gt;
&lt;br /&gt;
 APPLICATION (for example Joomla, Patchtester, Weblinks or your Extension name)&lt;br /&gt;
 + CLIENT (in Joomla we use it for defining if is Installation, Administrator or Frontend&lt;br /&gt;
 + CLIENT PART (In Joomla we use it following the menu are were it belongs: Components, Menus, System,...)&lt;br /&gt;
 + PAGE NAME (The Page name) &lt;br /&gt;
 + Page&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 JoomlaAdministratorLoginPage&lt;br /&gt;
 JoomlaAdministratorSystemGlobalconfigurationPage&lt;br /&gt;
 JoomlaInstallationConfigurationPage&lt;br /&gt;
&lt;br /&gt;
And they are located with a folder estructure similar to:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_pages_folder_structure.png|framed|center|Folder estructure for Pages in System Tests]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remind that in Codeception 2.0 you need to specify each folder in the acceptance/_bootstrap.php file:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
// Here you can initialize variables that will be available to your tests&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/installation&#039;);&lt;br /&gt;
\Codeception\Util\Autoload::registerSuffix(&#039;Page&#039;, __DIR__.DIRECTORY_SEPARATOR.&#039;_pages/joomla/administrator&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation ====&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#PageObjects&lt;br /&gt;
&lt;br /&gt;
=== Step Objects ===&lt;br /&gt;
Step Objects are classes which contains steps which are to be executed on the application to perform certain operations, step objects make use of page objects to perform these actions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class JoomlaAdministratorLoginSteps extends \AcceptanceTester&lt;br /&gt;
{&lt;br /&gt;
	/**&lt;br /&gt;
	 * Function to execute an Admin Login for Joomla 3&lt;br /&gt;
	 *&lt;br /&gt;
	 * @return void&lt;br /&gt;
	 */&lt;br /&gt;
	public function doAdministratorLogin($user, $password)&lt;br /&gt;
	{&lt;br /&gt;
		$I = $this;&lt;br /&gt;
		$I-&amp;gt;amOnPage(\JoomlaAdministratorLoginPage::$URL);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;username&#039;], $user);&lt;br /&gt;
		$I-&amp;gt;fillField(\JoomlaAdministratorLoginPage::$elements[&#039;password&#039;], $password);&lt;br /&gt;
		$I-&amp;gt;click(&#039;Log in&#039;);&lt;br /&gt;
		$I-&amp;gt;see(&#039;Category Manager&#039;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More info: http://codeception.com/docs/07-AdvancedUsage#StepObjects&lt;br /&gt;
&lt;br /&gt;
== Setting Up Codeception ==&lt;br /&gt;
=== setting up the repository ===&lt;br /&gt;
&#039;&#039;&#039;clone the directory&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Fork [https://github.com/joomla-projects/com_localise com_localise]&lt;br /&gt;
# &lt;br /&gt;
# Git clone git@github.com:*your-github-profile-name*/com_localise.git&lt;br /&gt;
&lt;br /&gt;
=== Testing with Codeception ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to get and run codeception, via PHAR or via Composer. Using &#039;&#039;&#039;Composer is recommended&#039;&#039;&#039; (because we are using in some tests the Codeception 2.1 development version not available in the composer.phar).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Using Composer&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    You need to have Composer in your system, if not download it from here: https://getcomposer.org/&lt;br /&gt;
&lt;br /&gt;
    Step 1: composer update&lt;br /&gt;
&lt;br /&gt;
    Step 2: run Codeception by doing: php vendor/bin/codecept build&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Codeception.phar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    Linux Machine  : wget http://codeception.com/codecept.phar&lt;br /&gt;
&lt;br /&gt;
    Windows Machine: Download from [http://codeception.com/install codecept.phar]&lt;br /&gt;
&lt;br /&gt;
    Step1 : php ./codecept.phar build&lt;br /&gt;
&lt;br /&gt;
=== Running the Test ===&lt;br /&gt;
&lt;br /&gt;
Rename tests/acceptance.suite.dist.yml to tests/acceptance.suite.yml&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 1: Modify the configuration at tests/acceptance.suite.yml to fit your server details.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Step 2: php codecept.phar run&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
with --steps to see a step-by-step report on the performed actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --steps&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with --html. This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be store in tests/_output/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run --html&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To activate the debug mode in Codeception just add the parameter --debug when you run the tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
php vendor/bin/codecept run acceptance --debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices at Testing ==&lt;br /&gt;
=== When do not use contains ===&lt;br /&gt;
We do not recommend to use the function contains on XPath because is not specific and can create false positives at tests.&lt;br /&gt;
See: https://github.com/joomla-projects/GSOC-Webdriver_system_tests_for_CMS/pull/99#issuecomment-69004191&lt;br /&gt;
=== Always add xPath locators to your tests ===&lt;br /&gt;
Performance in tests is very important. You can reduce dramatically the time spent on a test with just adding a few extra locators. For example, the following code pertains to a test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// see($text, $selector = null)&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the previous code we are not facilitating the &amp;quot;Selector&amp;quot; so Codeception will have to search for the element in all the HTML. Doing this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the tests went from: Time: 1.17 minutes&lt;br /&gt;
to: Time: 49.18 seconds&lt;br /&gt;
&lt;br /&gt;
You can see this video of a real example: http://www.youtube.com/watch?v=0JCv0BR2yZY&lt;br /&gt;
&lt;br /&gt;
Losing 30 seconds in every Assertion can delay your tests dramatically. Therefore, remind always to add xPath locators to all your Assertions.&lt;br /&gt;
[[Category:Automated Testing]]&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;see ====&lt;br /&gt;
Do not use &#039;&#039;see&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;see(&#039;Your article has been published&#039;, &#039;#messages&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using locators in $I-&amp;gt;waitForText ====&lt;br /&gt;
Do not use &#039;&#039;waitForText&#039;&#039; without locator:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;);&lt;br /&gt;
&lt;br /&gt;
// Right:&lt;br /&gt;
$I-&amp;gt;waitForText(&#039;Finalisation&#039;, 10, &#039;h3&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Quote and Double Quotes in Compex XPaths ===&lt;br /&gt;
Sometimes you will have to write XPaths that looks like:&lt;br /&gt;
&lt;br /&gt;
 //button[@onclick=&#039;Joomla.submitbutton(&amp;quot;config.save.application.apply&amp;quot;)&#039;]&lt;br /&gt;
&lt;br /&gt;
When moved to a Page Object you will probably will face this situation:&lt;br /&gt;
&lt;br /&gt;
[[File:System_tests_error_escaping_quotes_on_xpaths.png|framed|center|Typical issue when you write a long XPath in a Page objet]]&lt;br /&gt;
&lt;br /&gt;
To avoid it remind to escape the quotes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// Wrong&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
// Right&lt;br /&gt;
public static $elements = array(&lt;br /&gt;
   &#039;Save&#039; =&amp;gt; &amp;quot;//button[@onclick=\&amp;quot;Joomla.submitbutton(&#039;config.save.application.apply&#039;)\&amp;quot;]&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
	<entry>
		<id>https://docs.sandbox.joomla.org/index.php?title=File:System_tests_error_escaping_quotes_on_xpaths.png&amp;diff=161268</id>
		<title>File:System tests error escaping quotes on xpaths.png</title>
		<link rel="alternate" type="text/html" href="https://docs.sandbox.joomla.org/index.php?title=File:System_tests_error_escaping_quotes_on_xpaths.png&amp;diff=161268"/>
		<updated>2015-03-03T19:06:07Z</updated>

		<summary type="html">&lt;p&gt;Javiparati: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Licensing ==&lt;br /&gt;
{{JEDL}}&lt;/div&gt;</summary>
		<author><name>Javiparati</name></author>
	</entry>
</feed>