<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Codeception</title>
    <link>https://codeception.com/</link>
    <atom:link href="https://codeception.com/rss.xml" rel="self" type="application/rss+xml" />
    <description>Codeception: BDD-style testing in PHP</description>
    <language>en-us</language>
    <pubDate>Thu, 23 Apr 2026 19:25:44 +0000</pubDate>
    <lastBuildDate>Thu, 23 Apr 2026 19:25:44 +0000</lastBuildDate>

    
    <item>
      <title>Codeception 5</title>
      <link>https://codeception.com/07-28-2022/codeception-5.html</link>
      <pubDate>Thu, 28 Jul 2022 08:00:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-28-2022/codeception-5</guid>
      <description><![CDATA[ <p>Codeception 5.0 is out!</p>

<p>This release is <strong>PHP 8+</strong> only, so we are back on track with modern PHP. We are <strong>dropping support for PHPUnit &lt; 9</strong>, and are technically ready for PHPUnit 10. And we also support <strong>Symfony 6</strong> without dropping support of previous Symfony versions. As always, we did our best to keep backward compatibility so if you can update your dependencies, all tests should be working for you.</p>

<p>So let’s take a look at some new features:</p>

<h2 id="new-directory-structure">New Directory Structure</h2>

<p>Codeception 5 will follow the <a href="https://www.php-fig.org/psr/psr-12/">PSR-12 coding standard</a>. So all tests and classes will have their own namespace <code class="language-plaintext highlighter-rouge">Tests</code>. The directory structure was updated accordingly:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tests/
  _output
  Acceptance
  Functional
  Support/
    _generated/
    Data/
    Helper/
  Unit/
</code></pre></div></div>

<p>All suite names have their own namespace, as well as actor and helper classes:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>

<span class="kn">namespace</span> <span class="nn">Tests\Acceptance</span><span class="p">;</span>

<span class="kn">use</span> <span class="err">\</span><span class="nc">Tests\Support\AcceptanceTester</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">LoginCest</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">tryToTest</span><span class="p">(</span><span class="kt">AcceptanceTester</span> <span class="nv">$I</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This new directory structure will be generated by running <code class="language-plaintext highlighter-rouge">codecept bootstrap</code>.</p>

<h3 id="upgrading-from-codeception-4">Upgrading from Codeception 4</h3>

<p>Codeception 5 is compatible with the Codeception 4 directory structure. So if you don’t want to change your file locations now, just keep your existing <code class="language-plaintext highlighter-rouge">codeception.yml</code>, and everything’s fine.</p>

<p>However, if you want to upgrade to the new Codeception 5 directory structure (recommended), here’s the new default <code class="language-plaintext highlighter-rouge">codeception.yml</code>:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">namespace</span><span class="pi">:</span> <span class="s">Tests</span>
<span class="na">support_namespace</span><span class="pi">:</span> <span class="s">Support</span>
<span class="na">paths</span><span class="pi">:</span>
    <span class="na">tests</span><span class="pi">:</span> <span class="s">tests</span>
    <span class="na">output</span><span class="pi">:</span> <span class="s">tests/_output</span>
    <span class="na">data</span><span class="pi">:</span> <span class="s">tests/Support/Data</span>
    <span class="na">support</span><span class="pi">:</span> <span class="s">tests/Support</span>
    <span class="na">envs</span><span class="pi">:</span> <span class="s">tests/_envs</span>
<span class="na">actor_suffix</span><span class="pi">:</span> <span class="s">Tester</span>
<span class="na">extensions</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">Codeception\Extension\RunFailed</span>
</code></pre></div></div>

<p>Next steps:</p>

<ol>
  <li>Capitalize your suite configuration files:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">acceptance.suite.yml</code> =&gt; <code class="language-plaintext highlighter-rouge">Acceptance.suite.yml</code></li>
      <li><code class="language-plaintext highlighter-rouge">functional.suite.yml</code> =&gt; <code class="language-plaintext highlighter-rouge">Functional.suite.yml</code></li>
      <li><code class="language-plaintext highlighter-rouge">unit.suite.yml</code> =&gt; <code class="language-plaintext highlighter-rouge">Unit.suite.yml</code></li>
    </ul>
  </li>
  <li>Inside those configuration files, update to the new namespace:
    <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="na">modules</span><span class="pi">:</span>
     <span class="na">enabled</span><span class="pi">:</span>
         <span class="pi">-</span> <span class="s">Tests\Support\Helper\Unit</span>
</code></pre></div>    </div>
  </li>
  <li>In your <code class="language-plaintext highlighter-rouge">composer.json</code>, update to the new namespace:
    <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="nl">"autoload-dev"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
     </span><span class="nl">"psr-4"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
         </span><span class="nl">"Tests\\"</span><span class="p">:</span><span class="w"> </span><span class="s2">"tests/"</span><span class="w">
     </span><span class="p">}</span><span class="w">
 </span><span class="p">}</span><span class="err">,</span><span class="w">
</span></code></pre></div>    </div>
  </li>
  <li>In your <code class="language-plaintext highlighter-rouge">tests/Support/Acceptance|Functional|UnitTester.php</code> files, update to the new namespace <code class="language-plaintext highlighter-rouge">Tests\Support</code></li>
  <li>If you have <code class="language-plaintext highlighter-rouge">tests/Support/Helper/Acceptance|Functional|Unit.php</code> files, update their namespace to <code class="language-plaintext highlighter-rouge">Tests\Support\Helper</code></li>
  <li>Run <code class="language-plaintext highlighter-rouge">vendor/bin/codecept build</code> to create the files in <code class="language-plaintext highlighter-rouge">tests/Support/_generated</code></li>
  <li>Modify the namespaces in all your test/cest files</li>
  <li>Run the tests with capitalized suite names: <code class="language-plaintext highlighter-rouge">vendor/bin/codecept run Unit</code></li>
</ol>

<h2 id="attributes">Attributes</h2>

<p>Annotations were an essential part of the Codeception testing framework. Even though they were not native language constructs, they proved to be quite good to separate a test from its metadata. We believe that test should not include code that doesn’t belong to the test scenario.</p>

<p>So we were glad that native attributes have landed in the PHP world. In this release we encourage you to start using them:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#[Group('important')]</span>
<span class="c1">#[Group('api')]</span>
<span class="c1">#[Examples('GET', '/users')]</span>
<span class="c1">#[Examples('GET', '/posts')]</span>
<span class="c1">#[Env('staging-alpha')]</span>
<span class="c1">#[Env('staging-beta')]</span>
<span class="c1">#[Env('production')]</span>
<span class="c1">#[Prepare('startServices')]</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testApiRequests</span><span class="p">(</span><span class="kt">ApiTester</span> <span class="nv">$I</span><span class="p">,</span> <span class="kt">Example</span> <span class="nv">$e</span><span class="p">)</span>
<span class="p">{</span>
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">(</span><span class="nv">$e</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nv">$e</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseCodeIsSuccessful</span><span class="p">();</span>
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseIsJson</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As you see, attributes decouple all preparation steps, keeping the test scenario minimal. We also keep supporting annotations, so an urgent upgrade is not needed. Attributes can’t do anything that traditional annotations can’t, they are just a modern alternative.</p>

<p>List of available attributes (all under <code class="language-plaintext highlighter-rouge">Codeception\Attribute</code> namespace):</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Before</code> - specifies a method that should be executed before each test</li>
  <li><code class="language-plaintext highlighter-rouge">After</code> - specifies a method that should be executed after each test</li>
  <li><code class="language-plaintext highlighter-rouge">Group</code> - sets the group for the test</li>
  <li><code class="language-plaintext highlighter-rouge">Skip</code> - skips the current test</li>
  <li><code class="language-plaintext highlighter-rouge">Incomplete</code> - marks test as incomplete</li>
  <li><code class="language-plaintext highlighter-rouge">Depends</code> - sets the test that must be executed before the current one</li>
  <li><code class="language-plaintext highlighter-rouge">Prepare</code> - sets a method to execute to initialize the environment (launch server, browser, etc)</li>
  <li><code class="language-plaintext highlighter-rouge">DataProvider</code> - specifies a method that provides data for data-driven tests</li>
  <li><code class="language-plaintext highlighter-rouge">Examples</code> - sets data for data-driven tests inside the annotation</li>
  <li><code class="language-plaintext highlighter-rouge">Env</code> - sets environment value for the current test</li>
  <li><code class="language-plaintext highlighter-rouge">Given</code>, <code class="language-plaintext highlighter-rouge">When</code>, <code class="language-plaintext highlighter-rouge">Then</code> - marks a method as BDD step</li>
</ul>

<h2 id="debugging">Debugging</h2>

<p>Do you remember, <code class="language-plaintext highlighter-rouge">Hoa\Console</code>? Unfortunately, this library was deprecated and we were looking for a modern alternative that could power <code class="language-plaintext highlighter-rouge">codecept console</code> and <code class="language-plaintext highlighter-rouge">$I-&gt;pause();</code>. We switched to <a href="https://psysh.org">PsySH</a>, a PHP Read-Eval-Print Loop.</p>

<p>An interactive console is used to pause a test in the given state. While in pause you can try different Codeception commands, and check variable values. Instead of fixing tests blindly, you can start an interactive session. This is quite a similar effect you can get with a real debugger like XDebug but focused on Codeception commands. This is especially helpful for acceptance tests as the test scenario can be planned while executing a test. So the basic scenario can be written as:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pause</span><span class="p">();</span>
</code></pre></div></div>

<p>After opening a page you will be able to try commands in a browser. If a command succeeds you can use it in your tests.</p>

<p>Also new functions were added:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">codecept_pause()</code> - starts interactive pause anywhere in debug mode</li>
  <li><code class="language-plaintext highlighter-rouge">codecept_debug()</code> - prints a variable to console using Symfony VarDumper</li>
</ul>

<h3 id="upgrading-from-codeception-4-1">Upgrading from Codeception 4</h3>

<p>Just remove <code class="language-plaintext highlighter-rouge">hoa/console</code> from your <code class="language-plaintext highlighter-rouge">composer.json</code>.</p>

<h2 id="sharding">Sharding</h2>

<p>The <a href="/docs/ParallelExecution">Parallel Execution guide</a> has been rewritten and focused on a new feature: sharding. It is the simplest way to run slow tests (think of acceptance tests first) in parallel on multiple agents.</p>

<p>In this case, you specify the batch of tests that should be executed independently and each job picks up its own not intersecting group of tests to run them.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># first job</span>
./vendor/bin/codecept run <span class="nt">--shard</span> 1/3

<span class="c"># second job</span>
./vendor/bin/codecept run <span class="nt">--shard</span> 2/3

<span class="c"># third job</span>
./vendor/bin/codecept run <span class="nt">--shard</span> 3/3
</code></pre></div></div>

<p>This feature reduces the need for complex configuration and usage of <code class="language-plaintext highlighter-rouge">robo</code> task runner to split tests.</p>

<p>It is recommended to use sharding to parallelize tests between multiple jobs as the simplest approach. Unfortunately, PHP doesn’t have native multi-threading for test parallelization, and even if it had, it doesn’t solve the problem of running slow browser tests that are interacting with the entire application. So only horizontal scaling by jobs can be suggested as a long-running approach. The more build agents you add to your Continuous Integration server, the faster tests will run. That’s it!</p>

<h2 id="grep-and-filter">Grep and Filter</h2>

<p>New options <code class="language-plaintext highlighter-rouge">--grep</code> and <code class="language-plaintext highlighter-rouge">--filter</code> were introduced to select tests by part of their name. Actually, it is the same option and an alias. <code class="language-plaintext highlighter-rouge">--grep</code> is a common way to select tests to execute in NodeJS test runners, so we ported it to Codeception. But as usual, specific tests can also be executed by group or specifying a test signature.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./vendor/bin/codecept run <span class="nt">--grep</span> <span class="s2">"user"</span>
</code></pre></div></div>

<h2 id="other-changes">Other Changes</h2>

<p>Please go through the list of changes introduced to see if they don’t affect your codebase:</p>

<ul>
  <li>Requires PHP 8.0 or higher</li>
  <li>Compatible with PHPUnit 9 and ready for PHPUnit 10</li>
  <li>Compatible with Symfony 4.4 - 6.0</li>
  <li>Stricter check for phpdotenv v5 (older versions are not supported)</li>
  <li>Throw exception if actor setting is missing in suite configuration</li>
  <li>Removed <code class="language-plaintext highlighter-rouge">generate:cept</code> command (Cept format is deprecated)</li>
  <li>Removed settings <code class="language-plaintext highlighter-rouge">disallow_test_output</code> and <code class="language-plaintext highlighter-rouge">log_incomplete_skipped</code>.</li>
  <li>Removed setting <code class="language-plaintext highlighter-rouge">paths.log</code> (replaced by <code class="language-plaintext highlighter-rouge">paths.output</code> in Codeception 2.3)</li>
  <li>Removed suite setting <code class="language-plaintext highlighter-rouge">class_name</code> (replaced by <code class="language-plaintext highlighter-rouge">actor</code> in Codeception 2.3)</li>
  <li>Removed global setting <code class="language-plaintext highlighter-rouge">actor</code> (replaced by <code class="language-plaintext highlighter-rouge">actor_prefix</code> in Codeception 2.3)</li>
  <li>Removed <code class="language-plaintext highlighter-rouge">Configuration::logDir</code> method (replaced by <code class="language-plaintext highlighter-rouge">Configuration::outputDir</code> in 2.0)</li>
  <li>Moved <code class="language-plaintext highlighter-rouge">XmlBuilder</code> class to SOAP module</li>
  <li>Decoupled test execution and reporting from PHPUnit</li>
  <li>Custom reporters implementing <code class="language-plaintext highlighter-rouge">TestListener</code> are no longer supported and must be converted to Extensions</li>
  <li>Added optional value to <code class="language-plaintext highlighter-rouge">fail-fast</code> option (#6275) by #Verest</li>
  <li>Removed <code class="language-plaintext highlighter-rouge">JSON</code> and <code class="language-plaintext highlighter-rouge">TAP</code> loggers</li>
  <li>Removed code coverage blacklist functionality</li>
  <li>Removed deprecated class aliases
    <ul>
      <li>Codeception\TestCase\Test</li>
      <li>Codeception\Platform\Group</li>
      <li>Codeception\Platform\Group</li>
      <li>Codeception\TestCase</li>
    </ul>
  </li>
  <li>Introduced strict types in the code base.</li>
</ul>

<p><a href="https://raw.githubusercontent.com/Codeception/Codeception/5.0/CHANGELOG-5.x.md">Complete Changelog</a></p>

<hr />

<p>We are really happy that we are finally here with Codeception 5. This release was crafted during the war that happens in Ukraine. It is mentally and morally hard to work on tech products knowing that this peaceful virtual life can end at any moment by a random missile. Codeception was created in 2011 by <a href="https://github.com/DavertMik">Michael Bodnarchuk</a> in Kyiv, and today in 2022 he also stays there writing this post. If you want to support Codeception, all the Ukrainian PHP community, and all our brave nation who stands for democracy against this barbaric Russian invasion, consider <strong><a href="https://stand-with-ukraine.pp.ua">donating to Ukrainian charities</a></strong>. Not a single time. Every month until the war ends. Every time you travel or enjoy tasty food in a restaurant think of people who are forced to defend their land, or who fled their homes. Glory to Ukraine!</p>

<p>This release wouldn’t be possible without the hard work of <a href="https://github.com/Naktibalda">Gintautas Miselis</a> who keeps constant work on modernizing internals and keeping Codeception up to date. Also we are really thankful to <a href="https://github.com/TavoNiievez">Gustavo Nieves
</a> who did a lot of work transitioning Codeception to Symfony 6 and more! Thanks to our maintainers! If you want to support our work we have <a href="https://opencollective.com/codeception">OpenCollective</a>!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 4.0 Released</title>
      <link>https://codeception.com/12-18-2019/codeception-4.html</link>
      <pubDate>Wed, 18 Dec 2019 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/12-18-2019/codeception-4</guid>
      <description><![CDATA[ <p>We are finally here!</p>

<p>Codeception 4.0 is released and this means a lot for us!</p>

<p>After long months on splitting core into modules, publishing new packages and setting up build pipelines, we are proud to show you the result.</p>

<p>As you know - Codeception 4 changes the way it is installed. From now on, Codeception package won’t include any modules by default and you will need to install them manually. This can be a bit annoying at first but in the end, this will allow you to upgrade each package individually and not relying on the core.</p>

<p>In Codeception 4 we also <strong>added support for Symfony 5</strong>, so if you plan to use the latest Symfony components - you need to upgrade today.</p>

<h2 id="upgrade-to-codeception-4">Upgrade to Codeception 4</h2>

<p>To start upgrading to Codeception 4 bump a version in <code class="language-plaintext highlighter-rouge">composer.json</code> and run <code class="language-plaintext highlighter-rouge">composer update</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"codeception/codeception": "^4.0"
</code></pre></div></div>

<p>To simplify the upgrading process <strong>we introduced an upgrade script</strong> which will go through your config file and scan for all included modules. Corresponding packages will be added to composer.json, so you could install all Codeception modules you need.</p>

<p>Run upgrade script on current project:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php vendor/bin/codecept init upgrade4
</code></pre></div></div>

<p>The script will upgrade your <code class="language-plaintext highlighter-rouge">composer.json</code> file and it is recommended to run <code class="language-plaintext highlighter-rouge">composer update</code> immediately, so new modules will be installed.</p>

<p>If you use several Codeception configs for multiple bundles you will need to execute upgrade script for each of them:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php vendor/bin/codecept init upgrade4 -c src/app/frontend/
</code></pre></div></div>

<p>Congratulations! An upgrade is done. Now you will be able to use each module individually.</p>

<p><strong>Thanks to Gintautas Miselis @Naktibalda for splitting the core and adding Symfony 5 support</strong></p>

<h2 id="phar-distribution">Phar Distribution</h2>

<p>Codeception 4.0 will provide two phar files with selected modules included. One file will target PHP 7.2+ and include Symfony 4.4, PHPUnit 8 and newer versions of other libraries. Another file will target PHP 5.6 - 7.1 and include Symfony 3.4 and PHPUnit 5.7.</p>

<p>Target audience of phar files is acceptance testers, so framework modules won’t be included.
Here is the full list of bundled modules:</p>

<ul>
  <li>Amqp</li>
  <li>Apc</li>
  <li>Asserts</li>
  <li>Cli</li>
  <li>Db</li>
  <li>FileSystem</li>
  <li>FTP</li>
  <li>Memcache</li>
  <li>Mongodb</li>
  <li>PhpBrowser</li>
  <li>Queue</li>
  <li>Redis</li>
  <li>Rest</li>
  <li>Sequence</li>
  <li>Soap</li>
  <li>Webdriver</li>
</ul>

<p>Phar files will no longer be built on release of codeception/codeception, but on more ad-hoc basis either monthly or after important changes to core or some bundled module.</p>

<h2 id="whats-new-in-40">What’s new in 4.0</h2>

<p>Since 4.0 our <a href="https://codeception.com/changelog">longread changelogs</a> are gone. So to track changes in modules you will need to go to corresponding repositories and read changelogs. For instance, here is <a href="https://github.com/Codeception/module-db/releases">the changelog for Db module</a>.</p>

<p>However, we will still publish changelogs for core changes here. And one of the most interesting features coming to Codeception 4 is command stashing in interactive pause.</p>

<p>Codeception 3.0 introduced interactive pause for better writing and debugging tests. By adding <code class="language-plaintext highlighter-rouge">$I-&gt;pause()</code> to your tests you could try all Codeception commands while a test will be interrupted. This helps for browser testing and framework testing, so you could try commands in action before leaving a test.</p>

<p>In Codeception 4.0 this instrument was improved so you could automatically stash all successful commands:</p>

<p><img src="https://user-images.githubusercontent.com/846343/70369505-896e9000-18f5-11ea-8f31-76d6846a859c.png" alt="" /></p>

<p>Use hotkeys to save successful commands into a file. So you no longer need to keep in mind which commands you need to take into your test. Just copy all successful commands and paste them into a test.</p>

<p><em>Stashing was brought to you by Poh Nean</em></p>

<hr />

<p>Thank you for using Codeception, and thank you for staying with us these years. 
It is December 2019, so it means that <strong>Codeception turns 8</strong>. Through these years we reached 15Mln installations on Packagist, we are used in some well-known companies and we became a valuable part of PHP ecosystem.</p>

<p>We accept congratulations <a href="https://twitter.com/codeception">in Twitter</a> or <a href="https://opencollective.com/codeception">on OpenCollective</a>. If your business gets some value from Codeception it is ok to support its maintainers. Especially, today, when we have to maintain not one repository but 32! So, if possible, talk to your boss and ask for sponsoring Codeception. This means a lot to us, Codeception Team, and it will motivate us to work more on Codeception.</p>

<p>We say “thank you” to all our current and previous sponsors:</p>

<ul>
  <li>Thanks to <strong><a href="https://opencollective.com/themeisle">ThemeIsle</a></strong> for becoming our first regular financial contributor</li>
  <li>Thanks to Sami Greenbury, Lars Moelleken, Dan Untenzu for investing their own money into open-source</li>
  <li>Thanks to Rebilly and 2Amigos who fully supported the development since 2013 till 2016</li>
  <li>Thanks to Seravo for sponsoring Codeception 3.0 release.</li>
</ul>

<p>That’s all. Upgrade to Codeception 4 and improve your testing!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 4.0 and beyond</title>
      <link>https://codeception.com/10-22-2019/codeception-4.0-and-beyond.html</link>
      <pubDate>Tue, 22 Oct 2019 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-22-2019/codeception-4.0-and-beyond</guid>
      <description><![CDATA[ <p>Today we would like to share our plans for the future of Codeception. 
We are going to release two major versions soon and we are ready to do so!
If you want to stay on board and get the latest updates, please read this post carefully. We will explain the reasoning behind the new release process and the upgrade path, which should be pretty simple to you!</p>

<p>As you know, we are very proud of our policy of keeping backward compatible releases. We know that tests should be stable and reliable at first. If a business is still powered by PHP 5.6, this is a business issue, and we can’t force a company to upgrade all their servers and processes just to support some more testing.</p>

<h3 id="codeception-40-is-coming-50-is-on-the-way-be-prepared">Codeception 4.0 is coming, 5.0 is on the way. Be prepared!</h3>

<p>However, keeping backward compatibility is harder and harder because of our dependencies - PHPUnit &amp; Symfony. They all go forward, break API and require newer versions of PHP and to follow them we need to do the same.</p>

<p>But can’t leave you without upgrades even if you don’t plan to switch to the latest Symfony or PHPUnit. That’s why we announce <strong>decoupling of Codeception</strong>.</p>

<p>That’s right! Since Codeception 4.0 <strong>the core will be separated from Codeception modules and extensions</strong>. This allows you to get the latest updates for the modules you use while keeping running Codeception on PHP 5.6+ with your set of dependencies.</p>

<p><img src="/images/decoupled-modules.png" alt="" /></p>

<p><em>See all modules decoupled at <a href="https://github.com/codeception">Codeception organization</a></em></p>

<p>After Symfony 5 is released we will release Codeception 5.0, with a direct dependency on Symfony 5 components. If you never plan to upgrade to Symfony 5 you can keep using Codeception 4, as (again) all modules are independent of the core. Codeception 5 (and upcoming versions) will support only the latest major versions of Symfony &amp; PHPUnit.</p>

<p>Transforming into a new release takes time and requires hard work from the Codeception team. <strong>Many thanks go to Gintautas Miselis @Naktibalda</strong> for doing the hardest work on splitting modules into repositories. Maintaining many repositories instead of one also requires more involvement from us. It would be easier for us just to release major versions every year and ask you to upgrade. But we didn’t do that. We care about you.</p>

<p>That’s why we ask you to <strong>sponsor development of Codeception</strong>. Please talk to your boss, to your CTO, to your marketing team, to your CEO. Tell that reliable software comes with a cost and if tests save your life, it’s a good time to give back!</p>

<p>Now you donate in <a href="https://opencollective.com/codeception/">a few clicks on OpenCollective</a>!</p>

<p class="text-center">
<a href="https://opencollective.com/codeception/" class="btn btn-lg btn-success" role="button">Sponsor Codeception</a></p>

<p>Sponsors receive priority support from our team, can ask for consulting, and add their logo on our website! Over 15K PHP developers visit our website monthly. If your brand needs to be recognizable in the PHP community - sponsoring Codeception is a very good opportunity for you!</p>

<hr />

<p>From your side, we will prepare an upgrade script from version 3.x to 4.x. So once Codeception 4.0 is released you will be able to run a smooth upgrade.</p>

<p>We won’t accept patches to 3.1 branch, so please send your pull requests to the corresponding module repositories or to 4.0 branch of the core.</p>

<p>A few notes on a new release process:</p>

<ul>
  <li>Each module will be released independently. You won’t need to wait for a month for a patch.</li>
  <li>Documentation for modules on codeception.com will be updated each month.</li>
  <li>Phar will contain only framework-agnostic modules (PhpBrowser, WebDriver, REST, Db) and will have a rolling weekly release.</li>
</ul>

<p>Official 4.0 release announcement coming soon as we need to prepare our website site and update documentation. Stay tuned and consider donating Codeception. We require your support these days!</p>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 3.0</title>
      <link>https://codeception.com/04-24-2019/codeception-3.0.html</link>
      <pubDate>Wed, 24 Apr 2019 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/04-24-2019/codeception-3.0</guid>
      <description><![CDATA[ <p>It’s finally time to bring a new major version of Codeception to life! 
Through years of evolution and constant improvements we learned a lot and today we think we are bringing to you the best Codeception version so far. We still belive that simplicity of testing is important, that test code should be easy to read, write, and debug. And if you are reading this post you probably already discovered that.</p>

<p>Maintaining such project that tries to embrace all kind of frameworks and CMSes, from Symfony to WordPress, from Laravel to Magento, is challenging, but what we see that people from those communities send us patches regularly. Probably, our philosophy - separate tests from the framework, share similar solutions via modules, shows the way. And our awesome community continue to improve this project. Hey, just look into our changelog. Even patch releases contain HUGE list of improvements!</p>

<p>Ok, so what about Codeception 3.0?</p>

<h3 id="breaking-changes">Breaking Changes</h3>

<h4 id="phpunit-8-support">PHPUnit 8 Support</h4>

<p>In 3.0 release we didn’t break a lot of stuff. We tried, but probably we just leave that for next major release. 
So we do not bump supported PHP version. We are still <strong>PHP 5.6+ compatible</strong>, just because testing should be available for everyone. We still support all major frameworks and we keep PHPUnit 6, and PHPUnit 7 compatibility.</p>

<p>However, keeping all that parts together is hard. So we assume, in 3.0 you can get <strong>possible breaking change, as we bring PHPUnit 8 support</strong>. For everything else, the upgrade should be smooth for you. If you face issues upgrading, go and change phpunit version to 6 or 7 in your composer.json:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"phpunit/phpunit": "^7.0"
</code></pre></div></div>

<p>We say thank you to our core contributor <strong>@Naktibalda</strong> to bring PHPUnit 8 support without breaking compatibilitiy.
That was huge job, and if you look into our <code class="language-plaintext highlighter-rouge">codeception/phpunit-wrapper</code> project you will understand why.</p>

<h4 id="modules-removed">Modules Removed</h4>

<p>We also decided to drop some of old modules, which we hope no one uses. Here they are</p>

<ul>
  <li>AngularJS - it worked only for Angular 1</li>
  <li>ZF1 - framework outdated</li>
  <li>Yii1 - framework outdated</li>
  <li>Silex - framework outdated</li>
  <li>Facebook - module not maintained</li>
  <li>XMLRPC - module not maintained</li>
</ul>

<p>If you need them, just copy their code from the 2.5 branch and create a custom helper. However, we won’t support them any longer.</p>

<h4 id="changed-defaults">Changed Defaults</h4>

<p>If you use multi-session testing and <code class="language-plaintext highlighter-rouge">$I-&gt;haveFriend</code> commands, you will see your tests fail. <code class="language-plaintext highlighter-rouge">Friend</code> methods no longer included into <code class="language-plaintext highlighter-rouge">Codeception\Actor</code> class, so you should add them manually. In your <code class="language-plaintext highlighter-rouge">AcceptanceTester</code> class (or other class which uses multi session testing) include <code class="language-plaintext highlighter-rouge">Codeception\Lib\Actor\Shared</code> trait:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">AcceptanceTester</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Actor</span>
<span class="p">{</span>
    <span class="kn">use</span> <span class="nc">_generated\AcceptanceTesterActions</span><span class="p">;</span>
    <span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Lib\Actor\Shared\Friend</span><span class="p">;</span>
<span class="p">}</span>    
</code></pre></div></div>

<p>We also disabled conditional assertions for new setups (as people regularly misuse them), so if you want to use <code class="language-plaintext highlighter-rouge">canSee</code> methods you will need to enable them. We will take a look on that in next sections of this post.</p>

<h3 id="features">Features</h3>

<p>M-m-m… Now the most tasty thing. Yes, we wouldn’t do the major release without new features. Thanks to sponsorship from <strong>Seravo</strong> we could finish some features we had in our roadmap.</p>

<h4 id="improved-interactive-shell">Improved Interactive Shell</h4>

<p>This feature was backported from our friendly project <a href="https://codecept.io">CodeceptJS</a>. 
It brings a new full featured REPL interface into a test, so you could pause test execution and fire different commands into console.</p>

<p>This feature <strong>absolutely changes the way you write your functional and acceptance tests</strong>. Instead of blindly trying different commands and restart tests all the time, you could write:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pause</span><span class="p">();</span>
</code></pre></div></div>

<p>And start typing commands one by one, writing a test step by step. You copy successful commands into your tests, and in the end you get a fully working test. <strong>If you use WebDriver, you could write a complete acceptance test using one browser session</strong>.</p>

<p>Unlike, previous interactive shell implementation, this one based on <code class="language-plaintext highlighter-rouge">hoa/console</code>, so you can use Left, Right keys to edit your input. Better to show it.</p>

<p><img src="https://user-images.githubusercontent.com/220264/54929617-875ad180-4f1e-11e9-8fea-fc1b02423050.gif" alt="" /></p>

<p>Learn more about using interactive shell in our <a href="https://codeception.com/docs/02-GettingStarted#Interactive-Pause">updated Getting Started guide</a></p>

<h4 id="try--retry">Try &amp; Retry</h4>

<p>Those features were introduced to make browser testing less painful. In the world full of JavaScript and Single Page Applications, you can no longer rely on single <code class="language-plaintext highlighter-rouge">click</code>, or <code class="language-plaintext highlighter-rouge">fillField</code> commands. Sometimes you need to retry action few times to make perform it.</p>

<p>Now you can do that via <code class="language-plaintext highlighter-rouge">retry*</code> actions which can help to stabilize flaky steps in your tests:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="c1">// use</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">retryClick</span><span class="p">(</span><span class="s1">'Create'</span><span class="p">);</span>

<span class="c1">// instead of just</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Create'</span><span class="p">);</span>
</code></pre></div></div>

<p>This feature was also ported from CodeceptJS but implemented a bit differently. <a href="https://codeception.com/docs/03-AcceptanceTests#Retry">Learn how to use it</a> in updated Acceptance Testing guide.</p>

<p>What if your site behaves differently in different environments? Like showing the “Cookie” badge depending on region?
And you need to accept cookies notifications if the badge is shown? You can do it via <code class="language-plaintext highlighter-rouge">tryTo*</code> actions:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">tryToSeeElement</span><span class="p">(</span><span class="s1">'.alert.cookie'</span><span class="p">))</span> <span class="p">{</span>
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Accept'</span><span class="p">,</span> <span class="s1">'.cookie'</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Thanks to Iain Poulson from Delicious Brains for <a href="https://deliciousbrains.com/automated-testing-woocommerce/">showing this use case</a></p>

<p><a href="https://codeception.com/docs/03-AcceptanceTests#AB-Testing">Learn how to use it</a> in updated Acceptance Testing guide.</p>

<p>Try and Retry were implemented as <a href="https://codeception.com/docs/08-Customization#Step-Decorators">Step Decorators</a>. As you know, actor classes contain code generated parts, and step decorators allow to generate additional actions by wrapping methods of modules. Conditional Assertions (<code class="language-plaintext highlighter-rouge">canSee*</code> methods) were refactored as step decorators too. So you need to enable them explicitly on new setups.</p>

<h4 id="artifacts-in-output">Artifacts in Output</h4>

<p>Failed tests now contain list of all available artifcats. 
For REST API test each test will contain a body of last response to simplify debugging on CI servers.</p>

<p><img src="https://user-images.githubusercontent.com/220264/56475577-bec38c00-6492-11e9-998f-8bbf5f823f17.png" alt="" /></p>

<h3 id="install-or-upgrade">Install or Upgrade</h3>

<p>Codeception 3.0 is as easy to upgrade as bumping version to <code class="language-plaintext highlighter-rouge">^3.0</code> in <code class="language-plaintext highlighter-rouge">composer.json</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"codeception/codeception": "^3.0"
</code></pre></div></div>

<p>Also please read the <a href="https://codeception.com/changelog">changelog</a> for more details.</p>

<h3 id="final-notes">Final Notes</h3>

<p>Thanks for everyone who have been with us all this years and who helps making Codeception better every day. Again, thanks to <strong>Naktibalda</strong> for taking care of maintaining minor releases and building compatibility bridge.</p>

<p>Thanks to <strong>Otto Kekäläinen from <a href="https://seravo.com">Seravo</a></strong> for generous donation.</p>

<p>And a few words from Michael Bodnarchuk, who started Codeception 8 years ago:</p>

<blockquote>
  <p>As a person who is interested in quality and testing I was interested in answering the question: what needs to be tested at first place. And the best answer I found so far is to get that information from the user feedback. Sometimes, a bug can be found only by a regular user, without causing a stack trace. And what I’d love to see, that users of web site or web application could submit such bugreports instantly. That’s why I built <strong><a href="https://www.bugira.com">Bugira Bugtracker</a>, my new SaaS product to get bugreports from your users</strong>. If you like my projects like Codeception or CodeceptJS, please <a href="https://bugira.com">try Bugira</a> as well. It will help you to establish better communication with you users and build a better products!</p>
</blockquote>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.5: Snapshots</title>
      <link>https://codeception.com/09-24-2018/codeception-2.5.html</link>
      <pubDate>Mon, 24 Sep 2018 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-24-2018/codeception-2.5</guid>
      <description><![CDATA[ <p>The Autumn is a good time to start something new. How about new Codeception?
As you know, each minor release indicates some important change, new features we wanted to share.
This time we want to introduce you to</p>

<h2 id="snapshots">Snapshots</h2>

<p>That’s the new feature, which might be useful if you are tired of harcoding your data into fixtures. For instance, when you test the search engine you don’t know the exact list of items to check, however, you are interested that the list would be the same every time for a search term.
What about API responses? You don’t want to hardcode it fully but you may want to check that response is the same as it was before.</p>

<p>So now Codeception can do what <a href="https://github.com/php-vcr/php-vcr">php-vcr</a> was doing all the time. Saving data into the file (called snapshot), and comparing with it on next runs.</p>

<p>This is nice feature for testing REST APIs.</p>

<p>Let’s assume you have such JSON response.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"firstName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"John"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"lastName"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"doe"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"phoneNumbers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"type"</span><span class="w">  </span><span class="p">:</span><span class="w"> </span><span class="s2">"iPhone"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"number"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0123-4567-8888"</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"type"</span><span class="w">  </span><span class="p">:</span><span class="w"> </span><span class="s2">"home"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"number"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0123-4567-8910"</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>And you want to check that phone numbers are the same on each run.
For this we can use a snapshot.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">namespace</span> <span class="nn">Snapshot</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">PhoneNumberSnapshot</span> <span class="kd">extends</span> <span class="nc">Codeception\Snapshot</span> <span class="p">{</span>
  
    <span class="cd">/** @var \ApiTester */</span>
    <span class="k">protected</span> <span class="nv">$i</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="err">\</span><span class="nc">ApiTester</span> <span class="nv">$I</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">i</span> <span class="o">=</span> <span class="nv">$I</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">protected</span> <span class="k">function</span> <span class="n">fetchData</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">// return an array of phone numbers</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">i</span><span class="o">-&gt;</span><span class="nf">grabDataFromResponseByJsonPath</span><span class="p">(</span><span class="s1">'$.phoneNumbers[*].number'</span><span class="p">);</span>
    <span class="p">}</span>  

<span class="p">}</span>
</code></pre></div></div>

<p>Then in test we can check if data matches the snapshot by calling the snapshot class:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">function</span> <span class="n">testUsers</span><span class="p">(</span><span class="kt">ApiTester</span> <span class="nv">$I</span><span class="p">,</span> <span class="err">\</span><span class="nc">Snapshot\PhoneNumberSnapshot</span> <span class="nv">$shapsnot</span><span class="p">)</span>
<span class="p">{</span>  
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendGET</span><span class="p">(</span><span class="s1">'/api/users'</span><span class="p">);</span>
  <span class="nv">$snapshot</span><span class="o">-&gt;</span><span class="nb">assert</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>If the data changes, snapshot is easy to update. Just run the test in <code class="language-plaintext highlighter-rouge">--debug</code> mode. 
The snapshot will be overwritten with a new data.</p>

<p>So, the good thing about snapshots:</p>

<ul>
  <li>you don’t keep flaky data in your code</li>
  <li>you don’t need to hardcode data values</li>
  <li>data can be easily updated on change</li>
</ul>

<p>Use them!</p>

<hr />

<p>There are also some other minor changes:</p>

<ul>
  <li><strong><a href="https://codeception.com/docs/modules/Db#Example-with-multi-databases">Db module</a> now supports multiple database</strong> connections. If you use few databases we got you covered! That was a long awaited feature and finally we have a very nice implementation from @eXorus.</li>
  <li><code class="language-plaintext highlighter-rouge">--seed</code> parameter added to <code class="language-plaintext highlighter-rouge">run</code> so you could rerun the tests in same order. This feature works only if you enabled <a href="https://codeception.com/docs/07-AdvancedUsage#Shuffle">shuffle</a> mode.</li>
  <li>Possible breaking: <code class="language-plaintext highlighter-rouge">seeLink</code> behavior changed.
    <ul>
      <li>Previous: <code class="language-plaintext highlighter-rouge">$I-&gt;seeLink('Delete','/post/1');</code> matches <code class="language-plaintext highlighter-rouge">&lt;a href="/post/199"&gt;Delete&lt;/a&gt;</code></li>
      <li>Now: <code class="language-plaintext highlighter-rouge">$I-&gt;seeLink('Delete','/post/1');</code> does NOT match <code class="language-plaintext highlighter-rouge">&lt;a href="/post/199"&gt;Delete&lt;/a&gt;</code></li>
    </ul>
  </li>
</ul>

<p><a href="https://codeception.com/changelog">See changelog</a> for the complete list of fixes and improvements.</p>

<p>Thanks to all our contributors who made this release happen!</p>

<hr />

<h2 id="call-to-sponsors">Call to Sponsors!</h2>

<p>We try to keep Codeception going and bring more releases to you. If your company uses this framework and you’d like to give back please consider <strong>sponsoring Codeception</strong>. That’s right. We are asking to invest into open source, to get the features you expect and to give back to open source.</p>

<p>For instance, how would you like improving stability of WebDriver tests?
It would be cool to automatically <strong>retry failed steps</strong> and <strong>rerun failed tests</strong>. 
These could be a very cool features but they can’t be made without your help.</p>

<p>If you are interested consider sponsoring us:</p>

<p class="text-center">
<a href="https://docs.google.com/forms/d/e/1FAIpQLSeVJWu2HJTjAE81SLiYJ1xqxAXeNNSCR_GO9R0_4CKka_nFvA/viewform?usp=send_form" class="btn btn-lg btn-success" role="button">Sponsor Codeception</a></p>

<p>Yes, we also provide <a href="https://sdclabs.com/codeception?utm_source=codeception.com&amp;utm_medium=top_menu&amp;utm_term=link&amp;utm_campaign=reference">enterprise support</a> and <a href="https://sdclabs.com/trainings?utm_source=codeception.com&amp;utm_medium=top_menu&amp;utm_term=link&amp;utm_campaign=reference">trainings</a>. This is another way you can support the development. Thank you!</p>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.4 released</title>
      <link>https://codeception.com/02-27-2018/codeception-2.4-released.html</link>
      <pubDate>Tue, 27 Feb 2018 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-27-2018/codeception-2.4-released</guid>
      <description><![CDATA[ <p>Hello everyone! We’d like to announce the immediate <strong>availability of Codeception 2.4.0</strong>.</p>

<p>This follows up the PHPUnit release and mostly contains <strong>compatibility fixes for PHPUnit 7</strong>. Internal usage of PHPUnit in Codeception was switched to new namespaced class names. This doesn’t break any public APIs but can break some setups. That’s why this is a minor release with a proper announcement. Please upgrade and unless you have some PHPUnit version conflict you should not experience any issues.</p>

<p><strong>Upgrade Notice:</strong> If you have tests extending <code class="language-plaintext highlighter-rouge">PHPUnit_Framework_TestCase</code> (old-style names) you have two options:</p>

<ul>
  <li>Lock version for PHPUnit in composer.json: <code class="language-plaintext highlighter-rouge">"phpunit/phpunit":"^5.0.0"</code></li>
  <li>Update your codebase to extend tests from <code class="language-plaintext highlighter-rouge">Codeception\Test\Unit</code> (which won’t be changed in future).</li>
</ul>

<p>Codeception 2.4.0 is a stability release. We <strong>dropped unmaintained PHP 5.4 and PHP 5.5</strong>. But we keep compatibility with PHP 5.6 so if your company still uses PHP 5 (and we understand business reasons) you can install this update too. Codeception is still going to be maintained with PHP 5.6 compatibility in mind. We don’t break API just for the sake of clean code. We try to make things reliable.</p>

<p>In the same Codeception 2.3.9 is released, so if you want to get the latest changes and you still use old PHP, upgrade to this version.</p>

<p>In Codeception 2.4 you will also find new hooks for Cest files:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">_passed</code> is called when a test inside Cest is successful</li>
  <li><code class="language-plaintext highlighter-rouge">_failed</code> is called for unsuccessful tests</li>
  <li><code class="language-plaintext highlighter-rouge">_after</code> is called at the end of a test for both cases.</li>
</ul>

<p>Previously <code class="language-plaintext highlighter-rouge">_after</code> hook worked as <code class="language-plaintext highlighter-rouge">_passed</code> and that behavior was confusing. This was changed so it can be potentially a breaking change as well.</p>

<p><a href="https://codeception.com/changelog">See changelog</a> for the complete list of fixes and improvements.</p>

<p>Thanks to all our contributors who made this release happen!</p>

<hr />

<p>We also launched <a href="https://join.slack.com/t/codeception/shared_invite/enQtMzE2MzgxNzM1OTUzLTcwMmMxZjMxYTdkMzljMzNjNmNiNWQ0NGNjNTY0MjJlNWNjOTI0ZWU0Mjg4YmE5NTI0MmMwNDZmNzRhOTZmNWE">Codeception Slack</a> to talk about testing and Codeception.</p>

<p class="text-center">
<a href="https://join.slack.com/t/codeception/shared_invite/enQtMzE2MzgxNzM1OTUzLTcwMmMxZjMxYTdkMzljMzNjNmNiNWQ0NGNjNTY0MjJlNWNjOTI0ZWU0Mjg4YmE5NTI0MmMwNDZmNzRhOTZmNWE" class="btn-lg btn btn-info" role="button">Join Slack</a></p>

<p>We’d also love to <strong>see more contributors</strong> there. We need more talented developers to help to bring new features and fix the issues. It’s opensource, after all. We face constant challenges: new APIs, new libraries, new approaches, etc. And Codeception as a really big project would benefit from any help. We are open to accepting new maintainers, to discuss trends, to build a better product! As you know, we are merging 90% of submitted Pull Requests so if you are not contributing, please go ahead!</p>

<hr />

<p>We try to keep Codeception going and bring more releases to you. If your company uses this framework and you’d like to give back please consider <strong>sponsoring Codeception</strong>. That’s right. We are asking to invest into open source, to get the features you expect and to give back to open source.</p>

<p class="text-center">
<a href="https://docs.google.com/forms/d/e/1FAIpQLSeVJWu2HJTjAE81SLiYJ1xqxAXeNNSCR_GO9R0_4CKka_nFvA/viewform?usp=send_form" class="btn btn-lg btn-warning" role="button">Sponsor Codeception</a></p>

<p>Please show this form to your company bosses. If you want to have stable reliable product it’s ok to pay for that. Be our first official sponsors!</p>

<p>Yes, we also provide <a href="https://sdclabs.com/codeception?utm_source=codeception.com&amp;utm_medium=top_menu&amp;utm_term=link&amp;utm_campaign=reference">enterprise support</a> and <a href="https://sdclabs.com/trainings?utm_source=codeception.com&amp;utm_medium=top_menu&amp;utm_term=link&amp;utm_campaign=reference">trainings</a>. This is another way you can support the development. Thank you!</p>

 ]]></description>
    </item>
    
    <item>
      <title>Writing Better Tests: Riding The Command Bus</title>
      <link>https://codeception.com/08-04-2017/writing-better-tests-riding-the-command-bus.html</link>
      <pubDate>Fri, 04 Aug 2017 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-04-2017/writing-better-tests--riding-the-command-bus</guid>
      <description><![CDATA[ <p><img src="/images/command_bus.jpg" alt="" /></p>

<p>Before writing any line of test code we should think of how meaningful this test would be. The best code is the code you never write, you know. So if you ever begin to think of which parts of the application you should cover with tests.</p>

<ul>
  <li><a href="https://codeception.com/12-21-2016/writing-better-tests-expectation-vs-implementation.html">Part 1: Expectation vs Implementation</a></li>
  <li><a href="https://codeception.com/04-21-2017/writing-better-tests-obtaining-specification.html">Part 2: Obtaining Specification</a></li>
</ul>

<p>Let’s start with a heart of your application, the Business Logic.</p>

<h3 id="layered-architecture">Layered Architecture</h3>

<p>Depending on architecture Business logic could be in Controller (ough), in Model (ough-ough), or in a special Service layer, which is the most preferred way. Business Logic responsible for taking decisions: which entities are valid and which are not, who can create entities, what happens when the entity is stored. Service layer should delegate the database operations to the infrastructure level.</p>

<p><img src="/images/layered.png" alt="" /></p>

<p>Infrastructure level is purely technical. It just takes orders from Service layer and executes them. It doesn’t make any decisions on its own. In most cases, ORM should be at the infrastructure level.</p>

<p>While models or repositories do not contain any decision making logic <strong>it is not that important what ORM type to use</strong>: ActiveRecord or DataMapper.</p>

<h3 id="commandbus-and-domain-events">CommandBus and Domain Events</h3>

<p>One of the solution to separate business logic from everything would be the 
<strong>CommandBus</strong> architecture.</p>

<p><img src="/images/architecture.png" alt="" /></p>

<p>CommandBus is well-known in PHP community. Learn more about it from</p>

<ul>
  <li><a href="https://php-and-symfony.matthiasnoback.nl/2015/01/a-wave-of-command-buses/">A wave of command buses</a> blogpost by Matthias Noback</li>
  <li><a href="https://laracasts.com/series/commands-and-domain-events">Laracats</a></li>
  <li><a href="https://tactician.thephpleague.com">Tactician</a> library by Ross Tuck</li>
</ul>

<p>If the application implements CommandBus pattern it is easy to find the business logic. 
It is located in command handlers. So let’s test them!</p>

<h3 id="testing-commandhandler">Testing CommandHandler</h3>

<p>CommandHandler takes a command, calls the infrastructure services, and sends the domain events. In theory, CommandHandlers can be tested in isolation, with unit tests. Infrastructure services can be mocked and domain events can be caught. However, those tests may have a little sense. And here is why/</p>

<p>“Trust me, I will save this to database” - may say the test with mocked infrastructure. But there is no trust to it. To make the command handler reliable and reusable we need to ensure it does what it is expected to do.</p>

<p>Also, mocks comes with their price. While integration test is really similar to the actual business code, unit test is bloated with mock definitions. It will get hard to maintain and support it really soon:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="c1">// is that a business logic test?</span>
<span class="c1">// but no business inside of it</span>
<span class="nv">$eventDispatcher</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">createMock</span><span class="p">(</span><span class="nc">EventDispatcher</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="nv">$busDispatcher</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getMockBuilder</span><span class="p">(</span><span class="nc">BusDispatcher</span><span class="o">::</span><span class="n">class</span><span class="p">)</span>
   <span class="o">-&gt;</span><span class="nf">setMethods</span><span class="p">([</span><span class="s1">'dispatch'</span><span class="p">])</span>
   <span class="o">-&gt;</span><span class="nf">getMock</span><span class="p">();</span>

<span class="nv">$busDispatcher</span><span class="o">-&gt;</span><span class="nf">expects</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">exactly</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
   <span class="o">-&gt;</span><span class="nf">method</span><span class="p">(</span><span class="s1">'dispatch'</span><span class="p">)</span>
   <span class="o">-&gt;</span><span class="nf">withConsecutive</span><span class="p">(</span>
       <span class="p">[</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">isInstanceOf</span><span class="p">(</span><span class="nc">CreateAccount</span><span class="o">::</span><span class="n">class</span><span class="p">)],</span>
       <span class="p">[</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">isInstanceOf</span><span class="p">(</span><span class="nc">CreateCompany</span><span class="o">::</span><span class="n">class</span><span class="p">)]</span>
   <span class="p">);</span>

<span class="nv">$handler</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">RegisterUserHandler</span><span class="p">(</span><span class="nv">$eventDispatcher</span><span class="p">,</span> <span class="nv">$busDispatcher</span><span class="p">);</span>
<span class="c1">// ... </span>
</code></pre></div></div>

<p>Here we also mix <a href="https://codeception.com/12-21-2016/writing-better-tests-expectation-vs-implementation.html">implementation with a specification</a>, which is a pure sin. What if <code class="language-plaintext highlighter-rouge">dispatch</code> method will be renamed? What if we fire more than 2 commands in a call? How is this related to business?</p>

<p>Even you can mock services you shouldn’t always do it.</p>

<p>In most cases, <strong>business logic should be tested with an integration test</strong>. Because the database is an essential part of your application. You can’t deliver an app without a database. The same way you can’t make sure domain logic works as expected when nothing is stored in the database.</p>

<h3 id="testing-flarum-forum">Testing Flarum Forum</h3>

<p>As an example let’s pick <a href="https://flarum.org">Flarum</a> project which is a forum built on top of Illuminate components (Laravel) and Symfony Components. What is most important that it has the <a href="https://github.com/flarum/core/tree/master/src/Core/Command">Commands and CommandHandlers</a>. By looking at one directory we can learn what Flarum does. That’s awesome!</p>

<p>Looks like the #1 priority is to get all those Command Handlers tested.
We can use <a href="https://github.com/flarum/core/blob/master/src/Core/Command/StartDiscussionHandler.php">StartDiscussionHandler</a> to start.</p>

<p>For integration tests, we need to initialize Application with its Dependency Injection Container. Then, we fetch <code class="language-plaintext highlighter-rouge">StartDiscussionHandler</code> out of it:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="k">protected</span> <span class="k">function</span> <span class="n">_before</span><span class="p">()</span>
<span class="p">{</span>
    <span class="c1">// initialize Flarum app</span>
    <span class="nv">$server</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nf">Flarum\Forum\Server</span><span class="p">(</span><span class="nf">codecept_root_dir</span><span class="p">());</span>
    <span class="nv">$app</span> <span class="o">=</span> <span class="nv">$server</span><span class="o">-&gt;</span><span class="nf">getApp</span><span class="p">();</span>
    <span class="c1">// get StartDiscussionHandler from container</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">handler</span> <span class="o">=</span> <span class="nv">$app</span><span class="o">-&gt;</span><span class="nf">make</span><span class="p">(</span><span class="nc">StartDiscussionHandler</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When the handler is prepared we can write the first basic test:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testAdminCanStartADiscussion</span><span class="p">()</span>
<span class="p">{</span>
    <span class="c1">// ARRANGE: create command object with all required params</span>
    <span class="nv">$admin</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">find</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// User #1 is admin</span>
    <span class="nv">$command</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StartDiscussion</span><span class="p">(</span><span class="nv">$admin</span><span class="p">,</span> <span class="p">[</span> <span class="c1">// create command</span>
        <span class="s1">'attributes'</span> <span class="o">=&gt;</span> <span class="p">[</span>
            <span class="s1">'title'</span> <span class="o">=&gt;</span> <span class="s1">'How about some tests?'</span><span class="p">,</span>
            <span class="s1">'content'</span> <span class="o">=&gt;</span> <span class="s1">'We discuss testing in this thread'</span>
        <span class="p">]</span>
    <span class="p">],</span> <span class="s1">'127.0.0.1'</span><span class="p">);</span>
    <span class="c1">// ACT: proceed with handler</span>
    <span class="nv">$discussion</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">handler</span><span class="o">-&gt;</span><span class="nf">handle</span><span class="p">(</span><span class="nv">$command</span><span class="p">);</span>
    <span class="c1">// ASSERT: check response</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertNotNull</span><span class="p">(</span><span class="nv">$discussion</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="s1">'How about some tests?'</span><span class="p">,</span> <span class="nv">$discussion</span><span class="o">-&gt;</span><span class="n">title</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>How do you like this test? This test so tiny and so easy to read. Sure, we should add more assertions to find out that all the business rules are applied, but for now it’s ok to try the very basic scenario. Maintaining and extending this test will be a pleasure.</p>

<h3 id="a-bit-of-stubs-and-mocks">A bit of Stubs and Mocks</h3>

<p>Integration test represents a part of a system, a working component. 
Once it triggers the outer service, it should be mocked. 
In layered architecture, a class from a layer should have access to its neighbors, and to classes of lower levels. So in our case, CommandHandler of business logic can access other command handlers but should be banned from accessing other services or other command buses.</p>

<p>For sure, mailers, queues, and other asynchronous services should be replaced with stubs.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Your application has a heart. Don’t make it die from a heart attack. Write tests.
Write meaningful stable tests that will last.</p>

<p><em>Written by Michael Bodnarchuk</em></p>

<p style="background: rgba(255,255,0,0.3)">We provide <a href=" https://sdclabs.com/codeception?utm_source=codeception.com&amp;utm_medium=post&amp;utm_term=link&amp;utm_campaign=reference">consulting services</a> and trainings on Codeception and automated testing in general.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Drive your Browser Tests with Codeception</title>
      <link>https://codeception.com/07-11-2017/drive-your-browser-with-codeception.html</link>
      <pubDate>Tue, 11 Jul 2017 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-11-2017/drive-your-browser-with-codeception</guid>
      <description><![CDATA[ <p>In last few weeks Codeception received updates aimed to empower acceptance testing. 
We try to make PHP a better place for browser tests. As you know, QA engineers often prefer other languages like Java or Python for test automation. But PHP is not that bad by itself, it is simpler, it is faster in most cases, it has great IDEs. And for sure, we have Codeception. With it you can write the most complex acceptance tests in a simple scenario-driven manner.</p>

<p>So what was added in the last release?</p>

<h2 id="runprocess">RunProcess</h2>

<p><a href="https://codeception.com/extensions#RunProcess">RunProcess extension</a> was introduced.
Use it to easily start/stop Selenium Server, ChromeDriver, or other required services for a test suite.</p>

<p>Enable it in suite config or in environment:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># acceptance.suite.yml</span>
<span class="na">extensions</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">Codeception\Extension\RunProcess</span><span class="pi">:</span>
            <span class="pi">-</span> <span class="s">php -S 127.0.0.1:8000</span>
            <span class="pi">-</span> <span class="s">java -jar selenium-server.jar</span>

<span class="c1"># or inside environment config</span>
<span class="c1"># in this case, run tests as</span>
<span class="c1">#</span>
<span class="c1"># codecept run --env selenium</span>
<span class="na">env</span><span class="pi">:</span>
  <span class="na">selenium</span><span class="pi">:</span>
    <span class="na">extensions</span><span class="pi">:</span>
        <span class="na">enabled</span><span class="pi">:</span>
            <span class="pi">-</span> <span class="na">Codeception\Extension\RunProcess</span><span class="pi">:</span>
                <span class="pi">-</span> <span class="s">php -S 127.0.0.1:8000</span>
                <span class="pi">-</span> <span class="s">java -jar selenium-server.jar</span>           
</code></pre></div></div>

<p>Depending on the environment (dev host, CI server) you can easily switch setups if you use environment configs.</p>

<h2 id="smartwaits">SmartWaits</h2>

<p>This is the new unique feature of Codeception which incorporates <a href="https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits">implicit waits</a>. By itself, the implicit wait was available in Codeception with <code class="language-plaintext highlighter-rouge">wait: </code> option in WebDriver config. However, it was not usable, because by design it slowed down test execution. In this release, we introduce the <strong>SmartWait concept</strong>. Implicit waits are used only when they are really needed and disabled for all other cases. This makes tests extremely stable and fast.</p>

<p>Thus, a test won’t fail if expected element didn’t yet appear on a page but waits for it a few seconds more. Just set <code class="language-plaintext highlighter-rouge">wait: 5</code> to WebDriver config to try it and <a href="https://codeception.com/docs/03-AcceptanceTests#SmartWait">read the documentation</a>.</p>

<h2 id="customization">Customization</h2>

<p>Codeception took to much of browser control. Let give it back to you.
With <code class="language-plaintext highlighter-rouge">start: false</code> option you can disable autostart browser before a test, and create a browser session manually. Codeception doesn’t provide actions to start browser session inside a test (because it is supposed you already have one in a test), but you can write a custom method in a helper:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="c1">// support/Helper/Acceptance.php:</span>
<span class="c1">// </span>
<span class="k">public</span> <span class="k">function</span> <span class="n">startBrowser</span><span class="p">()</span>
<span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'WebDriver'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">_initializeSession</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">function</span> <span class="n">changeBrowser</span><span class="p">(</span><span class="nv">$browserName</span><span class="p">)</span>
<span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'WebDriver'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">_restart</span><span class="p">([</span><span class="s1">'browser'</span> <span class="o">=&gt;</span> <span class="nv">$browser</span><span class="p">]);</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">function</span> <span class="n">closeBrowser</span><span class="p">()</span>
<span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'WebDriver'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">_closeSession</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then these methods can be used inside a test.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="c1">// I prepare something for a test</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">startBrowser</span><span class="p">();</span>
<span class="c1">// I do something inside a browser</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">closeBrowser</span><span class="p">();</span>
</code></pre></div></div>

<p>If you use <a href="https://www.browserstack.com/">BrowserStack</a> you can use this features to set a test name dynamically to <a href="https://www.browserstack.com/automate/capabilities">capabilities</a>. Here is how can you do it in Acceptance Helper:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="c1">// inside Helper\Acceptance</span>
<span class="c1">// </span>
<span class="k">public</span> <span class="k">function</span> <span class="n">_before</span><span class="p">(</span><span class="kt">TestInterface</span> <span class="nv">$test</span><span class="p">)</span>
<span class="p">{</span>
    <span class="nv">$webDriver</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'WebDriver'</span><span class="p">);</span>
    <span class="nv">$name</span> <span class="o">=</span> <span class="nv">$test</span><span class="o">-&gt;</span><span class="nf">getMetadata</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">getName</span><span class="p">();</span>
    <span class="nv">$webDriver</span><span class="o">-&gt;</span><span class="nf">_capabilities</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="nv">$currentCapabilities</span><span class="p">)</span> <span class="k">use</span> <span class="p">(</span><span class="nv">$name</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$currentCapabilities</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nc">DesiredCapabilities</span><span class="p">(</span><span class="nv">$currentCapabilities</span><span class="p">);</span>
    <span class="p">});</span>    
    <span class="nv">$webDriver</span><span class="o">-&gt;</span><span class="nf">_initializeSession</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Please don’t forget to set <code class="language-plaintext highlighter-rouge">start: false</code> in config option, so browser wouldn’t be started twice!</p>

<h2 id="prepare">@prepare</h2>

<p>What if you need to change the configuration for a specific test? 
Let’s say you want to run all tests in Firefox but this specific one in Chrome? Or something like that.</p>

<p>We added new annotation <code class="language-plaintext highlighter-rouge">@prepare</code> which can be used in Cest and Test formats. It will execute a method which can change the configuration before the module is called.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="cd">/**
 * @prepare switchToFirefox
 */</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testSomethingInFirefox</span><span class="p">(</span><span class="kt">AcceptanceTester</span> <span class="nv">$I</span><span class="p">)</span>
<span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Detect Browser'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Firefox'</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">protected</span> <span class="k">function</span> <span class="n">switchToFirefox</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\Module\WebDriver</span> <span class="nv">$webDriver</span><span class="p">)</span>
<span class="p">{</span>
    <span class="nv">$webDriver</span><span class="o">-&gt;</span><span class="nf">_reconfigure</span><span class="p">([</span><span class="s1">'browser'</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This <code class="language-plaintext highlighter-rouge">@prepare</code> can be used not only for browser tests but everywhere. Use it wisely!</p>

<hr />

<p>Is that all? Almost.</p>

<p>We also updated WebDriver docs to include more options for <a href="https://codeception.com/docs/modules/WebDriver#Local-Testing">Local Testing</a>, like ChromeDriver. We also published a <a href="https://phptest.club/t/how-to-run-headless-chrome-in-codeception/1544">reference on running Chrome in Headless mode</a>.</p>

<p>Update to the latest <code class="language-plaintext highlighter-rouge">2.3.4</code> version to try all the new features.</p>

<p>We worked hard to bring all this stuff to you. Now is your turn: please help to spread the word and encourage more of your colleagues to use PHP and Codeception for web testing. Setting up Codeception for web tests nowadays is as simple as running:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept init acceptance
</code></pre></div></div>

<p>Happy testing!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.3</title>
      <link>https://codeception.com/05-22-2017/codeception-2-3.html</link>
      <pubDate>Mon, 22 May 2017 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-22-2017/codeception-2-3</guid>
      <description><![CDATA[ <p>Today the Codeception 2.3 sees the world. This is a stable release with almost no breaking changes but with new features you will probably like.</p>

<p><img src="/images/codeception2.3_banner.png" alt="" /></p>

<p>At first, we need to say “thank you” to <a href="https://github.com/MontealegreLuis">Luis Montealegre</a> for bringing <strong>PHPUnit 6.0 support</strong> to Codeception. This is done by using class aliases so this doesn’t break old PHPUnit versions, so as usual, Codeception can be used with PHPUnit 4.8 and higher. However, If you run PHP7+ and you experience PHPUnit issues in this release we recommend you to set <code class="language-plaintext highlighter-rouge">phpunit/phpunit</code> package to <code class="language-plaintext highlighter-rouge">^5.7.0</code> in your composer.json.</p>

<p>Supporting 3 major versions of PHPUnit may have its issues, so in next release, which is going to be 3.0 we will probably drop support for old PHPUnits and PHP &lt; 7.</p>

<p>Ok, let’s talk about other changes in this release!</p>

<h2 id="installation-templates">Installation Templates</h2>

<p>Codeception is a wide-range testing framework and sometimes it is hard to get it configured for a specific case. Nevertheless, you need only acceptance testing Codeception will still install all 3 test suites for you. In 2.3 we prepared installation templates: customized setup wizards that can configure tests for your needs.</p>

<p>To setup Codeception for acceptance testing with browser only you can run this command</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept init acceptance
</code></pre></div></div>

<p>After answering a few questions, you will be able to execute first browser test</p>

<p><img src="/images/codecept_acceptance.gif" alt="" /></p>

<p>The setup wizard will prepare only <code class="language-plaintext highlighter-rouge">acceptance</code> test suite with tests located in <code class="language-plaintext highlighter-rouge">tests</code> directory. Suite configuration will be stored in <code class="language-plaintext highlighter-rouge">codeception.yml</code>.</p>

<p><strong>For QA engineers <code class="language-plaintext highlighter-rouge">codecept init acceptance</code> is a new convenient way to start end-to-end testing in PHP</strong>.</p>

<p>We also included API and Unit templates for faster setup of REST API or unit tests:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept init api
codecept init unit
</code></pre></div></div>

<p>But the best thing about installation templates that they can be created by anyone! They can be placed inside a separate package and loaded by <code class="language-plaintext highlighter-rouge">init</code> command. A template class should be placed into <code class="language-plaintext highlighter-rouge">Codeception\Template</code> namespace and then it can be autoloaded. Installation templates are pretty simple, learn how to build your own by taking a look at <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Template/Acceptance.php#L67">Acceptance template as an example</a>.</p>

<p>We have added Installation templates to <a href="https://codeception.com/docs/08-Customization#Installation-Templates">Customization</a> guide and added a reference to <a href="https://codeception.com/docs/reference/InitTemplate">Codeception\InitTemplate</a> class.</p>

<h2 id="configuration-improvements">Configuration Improvements</h2>

<h4 id="suites-inside-main-config">Suites Inside Main Config</h4>

<p>Suites can be defined inside main config:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">actor_suffix</span><span class="pi">:</span> <span class="s">Tester</span>
<span class="na">paths</span><span class="pi">:</span>
    <span class="na">tests</span><span class="pi">:</span> <span class="s">.</span>
    <span class="na">log</span><span class="pi">:</span> <span class="s">_output</span>
    <span class="na">data</span><span class="pi">:</span> <span class="s">_data</span>
    <span class="na">support</span><span class="pi">:</span> <span class="s">_support</span>
<span class="na">suites</span><span class="pi">:</span>
    <span class="na">unit</span><span class="pi">:</span>
        <span class="na">path</span><span class="pi">:</span> <span class="s">.</span>
        <span class="na">actor</span><span class="pi">:</span> <span class="s">UnitTester</span>
        <span class="na">modules</span><span class="pi">:</span>
            <span class="na">enabled</span><span class="pi">:</span>
                <span class="pi">-</span> <span class="s">Asserts</span>
</code></pre></div></div>

<p>A good option if you have a single suite.</p>

<h4 id="suite-paths">Suite Paths</h4>

<p>The suite can have its custom path (specified by <code class="language-plaintext highlighter-rouge">path</code>). From config above expects unit tests to be placed into the root directory, where codeception.yml is located.</p>

<p><img src="https://cloud.githubusercontent.com/assets/220264/25978631/1cda7ba6-36cc-11e7-9db1-035b13cab3d4.png" alt="selection_201" /></p>

<h4 id="suites-with-no-actor">Suites With No Actor</h4>

<p>Suite can be defined without an actor, which is useful for unit testing</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">paths</span><span class="pi">:</span>
    <span class="na">tests</span><span class="pi">:</span> <span class="s">tests</span>
    <span class="na">log</span><span class="pi">:</span> <span class="s">tests/_output</span>
    <span class="na">data</span><span class="pi">:</span> <span class="s">tests/_data</span>
    <span class="na">support</span><span class="pi">:</span> <span class="s">tests/_support</span>
    <span class="na">envs</span><span class="pi">:</span> <span class="s">tests/_envs</span>
<span class="na">suites</span><span class="pi">:</span>
    <span class="na">unit</span><span class="pi">:</span>
        <span class="na">path</span><span class="pi">:</span> <span class="s">.</span>
        <span class="na">modules</span><span class="pi">:</span>
            <span class="na">enabled</span><span class="pi">:</span>
                <span class="pi">-</span> <span class="s">Asserts</span>
</code></pre></div></div>

<p>In this case, UnitTester won’t be created, as well as <code class="language-plaintext highlighter-rouge">_generated/UnitActions</code>. However, such suites won’t be able to use Cest and Cept files.</p>

<h4 id="naming-changes">Naming Changes</h4>

<p><code class="language-plaintext highlighter-rouge">class_name</code> suite in suite config replaced with <code class="language-plaintext highlighter-rouge">actor</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class_name: UnitTester =&gt; actor: UnitTester
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">actor</code> from global config is replaced with <code class="language-plaintext highlighter-rouge">actor_suffix</code> config option (which makes more sense).</p>

<p>All these changes are backward compatible, so old values in config will work.</p>

<h2 id="extensions">Extensions</h2>

<p>Dynamical loading of extensions was already with <code class="language-plaintext highlighter-rouge">--override</code> option but was not very usable. Now extensions can be loaded with <code class="language-plaintext highlighter-rouge">--ext</code> option:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept run <span class="nt">--ext</span> Recorder
</code></pre></div></div>

<p>or by providing a full class name</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept run <span class="nt">--ext</span> <span class="s2">"Codeception</span><span class="se">\E</span><span class="s2">xtension</span><span class="se">\R</span><span class="s2">ecorder"</span>
</code></pre></div></div>

<p>This can be used to enable a custom reporter. For this reason, the new <a href="https://codeception.com/extensions#DotReporter">DotReporter</a> has been added:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept run --ext DotReporter
</code></pre></div></div>

<p><img src="https://cloud.githubusercontent.com/assets/220264/26132800/4d23f336-3aab-11e7-81ba-2896a4c623d2.png" alt="selection_205" /></p>

<h2 id="db-populator">Db Populator</h2>

<p>From the early days of Codeception we had the Db module which was trying to do its best to populate database and clean up it between tests. However, parsing all possible SQL dialects and running them through PHP was not very effective. What if you could use native Database tools to import data instead of doing it from PHP? Why not!</p>

<p>In Codeception 2.3 we recommend to specify a command to load a database in <code class="language-plaintext highlighter-rouge">populator</code> option of Db module:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
       <span class="pi">-</span> <span class="na">Db</span><span class="pi">:</span>
          <span class="na">dsn</span><span class="pi">:</span> <span class="s1">'</span><span class="s">mysql:host=localhost;dbname=testdb'</span>
          <span class="na">user</span><span class="pi">:</span> <span class="s1">'</span><span class="s">root'</span>
          <span class="na">password</span><span class="pi">:</span> <span class="s1">'</span><span class="s">'</span>
          <span class="na">cleanup</span><span class="pi">:</span> <span class="no">true</span> <span class="c1"># run populator before each test</span>
          <span class="na">populate</span><span class="pi">:</span> <span class="no">true</span> <span class="c1"># run populator before all test</span>
          <span class="na">populator</span><span class="pi">:</span> <span class="s1">'</span><span class="s">mysql</span><span class="nv"> </span><span class="s">-u</span><span class="nv"> </span><span class="s">$user</span><span class="nv"> </span><span class="s">$dbname</span><span class="nv"> </span><span class="s">&lt;</span><span class="nv"> </span><span class="s">tests/_data/dump.sql'</span>
</code></pre></div></div>

<p>This approach is system-dependent, you can’t use the same config on Windows and Nix systems, but is much faster. Thanks to <a href="https://github.com/brutuscat">Mauro Asprea @brutuscat</a> for this feature.</p>

<h3 id="db-module-defaults">Db module defaults</h3>

<p>Important notice: we changed defaults for Db module, so <strong><code class="language-plaintext highlighter-rouge">cleanup</code> and <code class="language-plaintext highlighter-rouge">populate</code> options are disabled</strong> by default. They were quite dangerous in use, so we decided that you need to set them explicitly in Db module config.</p>

<hr />

<p>Codeception 2.2.12 has been released as well.
See complete <a href="https://codeception.com/changelog">changelog</a> for all notable changes.</p>

<hr />

<p>P.S. <strong>Codeception is seeking for Symfony module maintainer</strong>. If you use Codeception with Symfony and you’d like to improve it, please contact us at <code class="language-plaintext highlighter-rouge">team@codeception.com</code>. 
Maintainer responsibilities are: review issues, pull requests, update symfony demo app and so on. Take a part in project development and make open source brighter!</p>
 ]]></description>
    </item>
    
    <item>
      <title>New Addons Page</title>
      <link>https://codeception.com/05-09-2017/new-addons-page.html</link>
      <pubDate>Tue, 09 May 2017 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-09-2017/new-addons-page</guid>
      <description><![CDATA[ <p>As you know Codeception has a really nice ecosystem with lots of modules and extensions built by the community. Thanks for everyone who invest their time into building better testing tools. Sometimes we accept 3rd-party modules into Codeception core, sometimes we ask contributors to publish them as standalone packages.</p>

<p>Today we’d love to announce a minor but very nice change on our website. <strong>We updated the <a href="https://codeception.com/addons">Addons</a> page</strong> so community-built modules and extensions would look nice there. The new Addons page looks as slick as a marketplace but everything there is for free!</p>

<p>If you have a helper or an extension that might be useful to others, don’t hesitate to share it! New “cards” format for extensions and modules will make them more visible to others. You can also attach your pictures and set colors for cards to be even more visible (If you think your extensions worth it).</p>

<p>The philosophy of Codeception is: don’t reinvent the wheel, share testing solutions. Spend more time writing tests and not test support code. Get more powerful tools and make testing fun!</p>

<p>There are some tools you definitely should not miss:</p>

<ul>
  <li><a href="https://chrome.google.com/webstore/detail/codeception-testtools/jhaegbojocomemkcnmnpmoobbmnkijik">Codeception Extension for Chrome</a> created by Marcel Pociot.</li>
  <li><a href="https://github.com/jayhealey/Webception">WebCeption</a> a web-based Codeception runner.</li>
  <li><a href="https://codeception.com/docs/reference/Extensions#CodeceptionExtensionRecorder">Recorder</a> an official extension to capture screenshots after each step.</li>
  <li><a href="https://github.com/Codeception/VisualCeption">VisualCeption</a> and <a href="https://github.com/mendicm/css-regression">CSSRegression</a> to test visual regressions on site.</li>
</ul>

<p>and <a href="https://codeception.com/addons">many many others</a>! If you don’t have a module or extension but you still have some experience to share, write a few lines to the <a href="https://phptest.club/c/codeception/cookbook">Cookbook</a>.</p>

<p>Thamks for reading. Stay tuned for next cool updates!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Writing Better Tests: Obtaining Specification</title>
      <link>https://codeception.com/04-21-2017/writing-better-tests-obtaining-specification.html</link>
      <pubDate>Fri, 21 Apr 2017 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/04-21-2017/writing-better-tests--obtaining-specification</guid>
      <description><![CDATA[ <p>When you start implement testing in your development process you should always ask: which tests are important for this project. And there is no general answer to this question. “Test everything, everywhere” is not a good solution as well, by writing more and more lines of code you won’t stable software. Tests should be driven by specification, and specification comes from your business. Depending on that you should choose which areas are more important to cover with tests and which are less.</p>

<p><a href="https://codeception.com/12-21-2016/writing-better-tests-expectation-vs-implementation.html">Part 1: Expectation vs Implementation</a></p>

<p>It is always thought that you should have several acceptance tests, a dozen of functional, and a lot of unit or integration tests. However, If you develop a media portal it is more important to you, and for your business to have a good-looking UI. Same story if you develop new To-Do application focused on perfect UX. It is not much business logic for a To-Do app, but you need to ensure that everything user sees is slick. Even you have some internal bugs it is more important to you to assure that all buttons are visible, they can be easily clicked and so on.</p>

<p>Like in this app:</p>

<p><img src="/images/wunderlist.png" alt="" /></p>

<p>That’s right for this type of applications you should revert your testing pyramid. You should have lots of acceptance tests and few unit/integration.</p>

<p>If UI/UX is a part of your business, concentrate on acceptance (browser) tests. But if you run banking application, ecommerce solution, ERP or CRM, UI is not that important. Those applications include complex domain logic and internal quality is much more important than visual part.</p>

<p><img src="/images/test-layers.png" alt="" /></p>

<p>What if user by a bug creates 3 extra todos in To-Do app? Well, it doesn’t look nice but not a big deal. But what if user by a bug withdraws from ATM 3 times more money they own? That’s a real problem. In case, you <strong>deal with money or real</strong> things it is critically important to test all the business processes. Test all possible scenarios, all edge cases, make the domain to be 100% covered with tests.</p>

<p>That brings us to key idea of this post. There are two kinds of IT products:</p>

<ul>
  <li>software that automates business</li>
  <li>software that is a business by itself</li>
</ul>

<p>And depending on the kind of software you work on you have different priorities.
This also answers a question: “do I need BDD for my project”. In case, you are automating traditional business, you need to translate all business processes into a code, and you need ubiquitous languages for that. In case, you are building a new business, a startup, you probably don’t need that layer of complexity as presumably founders already speak the IT language.</p>

<p>So learn what is important in your business. What brings you money. What are the risks. Cover that part at first and think from business side and not from technical. This is how a business would understand the real value of automated tests.</p>

<p><em>Written by Michael Bodnarchuk</em></p>

<p style="background: rgba(255,255,0,0.3)">We provide <a href=" https://sdclabs.com/codeception?utm_source=codeception.com&amp;utm_medium=post&amp;utm_term=link&amp;utm_campaign=reference">consulting services</a> on Codeception and automated testing in general.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Writing Better Tests: Expectation vs Implementation</title>
      <link>https://codeception.com/12-21-2016/writing-better-tests-expectation-vs-implementation.html</link>
      <pubDate>Wed, 21 Dec 2016 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/12-21-2016/writing-better-tests--expectation-vs-implementation</guid>
      <description><![CDATA[ <p><img src="/images/car_test.jpg" alt="" /></p>

<p>What makes a meaningful test? This question should always be asked. No matter we write your tests first or tests after, they may stay in a project for years and it is pretty important them to test the things that really matters. Badly written tests can slow us down by constantly failing on each implementation change, and such tests can be written no matter you follow TDD or not. The idea of a test is to ensure that software works and not to freeze it at specific point.</p>

<p>Such situation happens when a test is bound to implementation details. We are choosing to rely on parts which we may consider to be stable but they are not. Whenever we come to unit testing and we are writing a mock we should understand that we change the reality, and how that artificial reality will survive the test of time. Consider using such test written in XIX century as an example:</p>

<div class="language-gherkin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">Given </span>I am drunk 
<span class="nf">And </span>I am in a pub
<span class="nf">And </span>I want to get home
<span class="nf">When </span>I order a cab
<span class="nf">Then </span>I expect to see 2 horses and carriage
<span class="nf">And </span>they bring me home
</code></pre></div></div>

<p>By ordering a cab nowadays you probably won’t expect to see 2 horses but you probably will get home even faster. In XXI century we still have pubs and we still need cabs to get home, that’s something stable in our world. The point is: you should not be worried of HOW you will be brought home: by horses, by car, by flying dragons or by teleport. That’s implementation details.</p>

<p>But how to understand what is stable and what is not? We need to use interfaces. Not that one which is written as <code class="language-plaintext highlighter-rouge">interface</code> keyword in PHP but a general term: User Interface, API. And that’s what makes unit testing and browser testing similar: <strong>we always need to rely on public interfaces for a test</strong>. If break this rule and we start to test private methods or raw values in database we are producing a synthetic tests which will lead us the very tricky path.</p>

<p>An opposite to follow public APIs is to depend on implementation.</p>

<p>But back to software development. Here is an example of <a href="https://github.com/jamescowie/magento2-generators/blob/develop/spec/Generators/Type/ModuleSpec.php">magento generators</a> written in PhpSpec. Not saying it is bad or not, but we use it to illustrate the point.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">ModuleSpec</span> <span class="kd">extends</span> <span class="nc">ObjectBehavior</span>
<span class="p">{</span>
  <span class="k">function</span> <span class="n">let</span><span class="p">(</span><span class="err">\</span><span class="nc">Symfony\Component\Filesystem\Filesystem</span> <span class="nv">$filesystem</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">beConstructedWith</span><span class="p">(</span><span class="nv">$filesystem</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">function</span> <span class="n">it_should_create_a_folder_given_a_valid_path</span><span class="p">(</span><span class="nv">$filesystem</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="nv">$path</span> <span class="o">=</span> <span class="s1">'app/code/test/test'</span><span class="p">;</span>
      <span class="nv">$filesystem</span><span class="o">-&gt;</span><span class="nf">exists</span><span class="p">(</span><span class="nv">$path</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">willReturn</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
      <span class="nv">$filesystem</span><span class="o">-&gt;</span><span class="nb">mkdir</span><span class="p">(</span><span class="nv">$path</span><span class="p">,</span> <span class="mo">0700</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">willReturn</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
      <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">make</span><span class="p">(</span><span class="nv">$path</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">shouldReturn</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The test is very descriptive: there is a class that depends on <code class="language-plaintext highlighter-rouge">Filesystem</code> and can be used to create a given folder. However, one line is questionable:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$filesystem</span><span class="o">-&gt;</span><span class="nb">mkdir</span><span class="p">(</span><span class="nv">$path</span><span class="p">,</span> <span class="mo">0700</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">willReturn</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
</code></pre></div></div>

<p>This is the mock that expects <code class="language-plaintext highlighter-rouge">mkdir</code> to be called with a specific parameters and to return an expected result. 
But is that stable to changes? What if at some point <code class="language-plaintext highlighter-rouge">mkdir</code> gets deprecated in favor of <code class="language-plaintext highlighter-rouge">mkdirPlus</code>, what if a method signature changes?</p>

<p>Well, in this current case we can be sure that this method won’t be changed. The reason is simple: it’s Symfony, it’s LTS, and its API is stable. But can you say that about internal classes of your application? That they are 100% documented and they won’t change their behavior in future.</p>

<p>When we change the implementation of <code class="language-plaintext highlighter-rouge">Module-&gt;make()</code> it still fits expected specification (‘it should create a folder given a valid path’), but the test fails. This happens because the test pretend to know too much. In similar manner a strict master doesn’t just ask apprentice to do the job. He thinks he knows better how to do it and provides him with a detailed instructions. He doesn’t care of the outcome but apprentice should understand the basics: disobedience will be prosecuted.</p>

<p>But what if the actual result is not important to us? What if we want to ensure that tested method took the right path. That what happens in a test above: the implementation is verified. Indeed, If you are master (senior developer) and you have an apprentice (junior), this works pretty well: you ask them to implement the method just the way you see it.</p>

<p>This makes a difference between <strong>testing behavior or testing result</strong>. Probably in most cases you want to test the real outcome, a result, but in some important areas you may need to test the behavior as well.</p>

<p>To test a result <strong>we should rely on public interfaces only. We can validate class only by calling public method of this class and its collaborators</strong>
In this case we need to call <code class="language-plaintext highlighter-rouge">$filesystem-&gt;exists('app/code/test/test')</code>, and make a class with in-memory filesystem. We can even make this class without using any mocking framework, just with <a href="https://php.net/manual/en/language.oop5.anonymous.php">anonymous classes</a>.</p>

<p>By making a test bound to implementation we are copying parts of that implementation into a test. This breaks the <em>DRY</em> principle. At some point test and code can be unsynchronized and this leads to fragility. If you change class, the test using a mock of that class may still pass, but actual code using it will fail, and this false positiveness is dangerous.</p>

<p>Overusing mocks also makes tests longer. Lines of test code you write doesn’t always convert to software quality. Actually, from the software developer experience the true is quite the contrary: the more code you write the more bugs you may introduce. And your tests are just the same as production code: they will evolve with your software and they needs to be maintained.</p>

<p>So the actionable advice here is to think <strong>what is important to you: a behavior or a result</strong> (no matter how it is achieved). Try to <strong>discover what is stable and what is not, rely on stable parts, and use public interfaces</strong>. Thanks for reading.</p>

<p><em>Written by Michael Bodnarchuk @davert.</em></p>

<p><em>Thanks to Nick Palamarchuk for the review and ideas.</em></p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.2 is here</title>
      <link>https://codeception.com/06-03-2016/codeception-2.2-is-here.html</link>
      <pubDate>Fri, 03 Jun 2016 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-03-2016/codeception-2.2-is-here</guid>
      <description><![CDATA[ <p>Today we are glad to announce that Codeception 2.2 is finally released. The first beta came in March and after there were 2 RC versions. We assume that everyone could already try the new branch and check its new sweet features like <a href="https://codeception.com/changelog"><strong>Gherkin support</strong>, <strong>Examples</strong> and others</a>. We hope that you will like new version as it brings true multi format support to your testing experience! What other tool can execute Gherkin features and PHPUnit tests? We already support 4 testing formats for code and scenario testing and it is quite easy to introduce more.</p>

<p>Despite its growth and feature richness Codeception is still the most simple tool for test automation. We updated documentation to keep up to date with latest changes and improved the learning experiences. Also we prepared some Case Study pages which will help you to setup Codeception for your application. Now it is easier to start with <a href="https://codeception.com/for/laravel">Laravel</a> and <a href="https://codeception.com/for/symfony">Symfony</a> apps.</p>

<p>If you have questions about Codeception you can ask them on our <strong>community forum</strong> which is <a href="https://phptest.club">PhpTestClub</a>. We plan to build a sustainable community, so If you use Codeception for a long please share your experience there, help others to get into the world of PHP testing.</p>

<h2 id="how-to-upgrade">How To Upgrade</h2>

<p>We encourage you to UPGRADE to 2.2. Please take a look into changes marked as <em>breaking</em>.</p>

<ul>
  <li>The most important change is introduction of <strong>module conflicts</strong>. If modules share the same interface they probably should not be used together except the cases when the modules are loaded partially. This way you can’t use <code class="language-plaintext highlighter-rouge">Laravel5</code> module with <code class="language-plaintext highlighter-rouge">WebDriver</code> but you can use <code class="language-plaintext highlighter-rouge">Laravel5</code> with <code class="language-plaintext highlighter-rouge">part: ORM</code> so only ORM actions to be loaded. This change is important in order to avoid confusion in your functional or acceptance tests. If you use 2 similar modules you can’t be sure which one is executed when you call <code class="language-plaintext highlighter-rouge">$I-&gt;amOnPage</code>. <a href="https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features.html#conflicts">Learn more</a> from previous blogpost.</li>
  <li>Please also note that <strong>Dbh and Laravel4 module were removed</strong> from core package and moved into separate packages.</li>
  <li><code class="language-plaintext highlighter-rouge">Codeception\TestCase</code> was replaced with <code class="language-plaintext highlighter-rouge">Codeception\TestInterface</code> to it is a good idea to replace its usages in your Helper files.</li>
  <li>Cept and Cest formats are no longer extend <code class="language-plaintext highlighter-rouge">PHPUnit_Framework_TestCase</code>, so they don’t have <code class="language-plaintext highlighter-rouge">expectException</code>, <code class="language-plaintext highlighter-rouge">getMock</code>, etc.</li>
</ul>

<p>Please <a href="https://codeception.com/changelog">read changelog</a> to learn more.</p>

<p>But wait, you may ask, why there are breaking changes in minor release? Does Codeception follow semver? 
Not right now but future releases will do. <strong>Next major version is going to be Codeception 3.0</strong> which sure will introduce breaking changes for good reason. Also we plan to decouple most of modules from core package to make faster release cycles for them. Codeception 2.2 is also marked as <em>minor</em> that its still support PHP 5.4. However, we encourage you to upgrade for future versions.</p>

<h2 id="new-features-described">New Features Described</h2>

<ul>
  <li><a href="https://codeception.com/docs/07-BDD">BDD and Gherkin</a></li>
  <li><a href="https://codeception.com/docs/07-AdvancedUsage#Examples">Examples</a></li>
  <li><a href="https://codeception.com/docs/06-ModulesAndHelpers#Dynamic-Configuration-With-Params">Params</a></li>
  <li><a href="https://codeception.com/docs/06-ModulesAndHelpers#Module-Conflicts">Module Conflicts</a></li>
  <li><a href="https://codeception.com/docs/09-Data#DataFactory">DataFactory</a></li>
  <li><a href="https://codeception.com/docs/03-AcceptanceTests#AngularJS-Testing">AngularJS</a></li>
  <li><a href="https://codeception.com/docs/08-Customization#Custom-Commands">Custom Commands</a></li>
  <li>New <a href="https://codeception.com/docs/modules/Redis">Redis</a> module</li>
  <li><a href="https://codeception.com/changelog">COMPLETE CHANGELOG</a></li>
</ul>

<hr />

<p>If you are using 2.1 and you won’t plan to upgrade in nearest future, you can still use releases from 2.2 branch. Minor fixes and improvements will still be accepted there. Also the site will contain documentation for 2.2 and 2.2 versions.</p>

<p>Try Codeception 2.2 today by installing it via Composer:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require "codeception/codeception: ~2.2" --dev
</code></pre></div></div>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.2 Beta</title>
      <link>https://codeception.com/03-26-2016/codeception-2.2-beta.html</link>
      <pubDate>Sat, 26 Mar 2016 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-26-2016/codeception-2.2-beta</guid>
      <description><![CDATA[ <p>Happy Easter, everyone! Ok, not actually everyone, but Happy Easter to those who celebrate it this weekend. 
If you do (or even not), you probably will have free time to play with something new. 
And yes, by <em>something</em> we mean a <strong>beta version of Codeception 2.2</strong>!</p>

<p>We already announced lots of changes in Codeception:</p>

<ul>
  <li><a href="https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features.html">Test Dependencies, Params, and Conflicts</a></li>
  <li><a href="https://codeception.com/03-10-2016/even-more-features-of-codeception.html">DataFactory, AngularJS, Examples, Custom Commands, …</a></li>
</ul>

<p>but we forgot the most important one. It is <strong>Gherkin Support</strong>, which allows you to combine business requirements with functional testing. Yes, <code class="language-plaintext highlighter-rouge">*.feature</code> files are now part of a family with Cest, Cept and Tests. Codeception is a tool for running all kind of tests and in this release we significantly improved test internal architecture and test formats.</p>

<p>But back to Gherkin.</p>

<div class="language-gherkin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">Feature</span><span class="p">:</span> ToDo items
  In order to get my tasks done
  As a motivated person
  I need to be able to organize my todo list

  <span class="kn">Scenario</span><span class="p">:</span> show current todos
    <span class="err">Given there are todo items</span><span class="p">:</span>
      <span class="p">|</span> <span class="nv">Task</span>             <span class="p">|</span> <span class="nv">State</span>   <span class="p">|</span>
      <span class="p">|</span> <span class="n">make</span> <span class="n">Gherkin</span> <span class="n">PR</span>  <span class="p">|</span> <span class="n">opened</span>  <span class="p">|</span>
      <span class="p">|</span> <span class="n">update</span> <span class="n">docs</span>      <span class="p">|</span> <span class="n">opened</span>  <span class="p">|</span>
      <span class="p">|</span> <span class="n">create</span> <span class="n">examples</span>  <span class="p">|</span> <span class="n">closed</span>  <span class="p">|</span>
    <span class="nf">When </span>I open my todos
    <span class="nf">Then </span>I should see 2 todo items
</code></pre></div></div>

<p>Complete Guide on BDD with Codeception is not ready yest, but you can start with generating first feature file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept g:feature &lt;suiteName&gt; &lt;featureName&gt;
</code></pre></div></div>

<p>We recommend to have a special <em>features</em> folder in acceptance or functional suite, so it could be symlinked to the <code class="language-plaintext highlighter-rouge">features</code> dir in root of your project. This way non-technical users can esaily access feature files, without need to examine actual tests.</p>

<p>Next thing to do is to describe feature with scenarios. When you are done, prepare scenario steps for implementation be running</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept gherkin:snippets &lt;suiteName&gt;
</code></pre></div></div>

<p>You will get a list of methods which should be included into your actor class (let’s say AcceptanceTester). 
Then you should have it implemented. In theory, you can use any method of any class annotated with <code class="language-plaintext highlighter-rouge">@Given</code>, <code class="language-plaintext highlighter-rouge">@When</code>, <code class="language-plaintext highlighter-rouge">@Then</code> to be the step definition. So don’t worry you will end up with everything to put in one context, you will have option to use multiple contexts depending on role, tags, etc. More about it in BDD guide coming in next weeks.</p>

<p>For those of you, who set your dependencies as “codeception/codecepton:*” and (with no settings of <code class="language-plaintext highlighter-rouge">"minimum-stability": "stable"</code> you will probably have some wonderful time once you get back from holidays. This release is considered minor, so it won’t break everything, but still has some breaking changes. We notified of breaking changes in earlier versions by “deprecation warnings”, and we actually removed lots of deprecated stuff. The most important breaking change is proper implementation of <a href="https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features.html#conflicts">Conflicts API</a>. Please make sure you are not using modules of the same kinds in your configs.</p>

<hr />

<p>Codeception 2.2-beta is available for installation only via Composer:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require --dev "codeception/codeception:2.2.0-beta"
</code></pre></div></div>

<p>Next steps to do:</p>

<ul>
  <li><a href="https://github.com/Codeception/Codeception/blob/master/CHANGELOG.md">Read the changelog</a>. Check for all breaking changes. Probably you will need to update your Helper classes.</li>
  <li>Refer to updated <a href="https://github.com/Codeception/Codeception/tree/master/docs/modules">module docs for this beta release</a> in master branch.</li>
</ul>

<p>Stable release will come in next week(s). The release date depends on reported issues and on progress of updating documentation.</p>

<p>Have nice weekends and testing time!
We, Codeception team, hope you will love our product.</p>

<p>P.S. Reported issues should include a version. Pull Requests should be sent to master branch.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Even More Features of Codeception 2.2</title>
      <link>https://codeception.com/03-10-2016/even-more-features-of-codeception.html</link>
      <pubDate>Thu, 10 Mar 2016 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-10-2016/even-more-features-of-codeception</guid>
      <description><![CDATA[ <p>Today we continue to show you new features of Codeception 2.2, planned to release this March.
In previous post we’ve got you acquainted with <a href="https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features.html">Test Dependencies, Params, and Conflicts</a>. This post will continue this overview, and we will start with some nice modules, which might be useful to you.</p>

<p>As you know, in Codeception we try to help developers and testers share their experience by providing set of shared pieces, and not to reinvent the wheel. Modules play exactly that role: you just include modules to fit your project, and write your tests, concentrating on its business logic, and not on implementation. 90% test steps in functional and acceptance tests are covered with out modules. So what do we have prepared for 2.2?</p>

<h3 id="datafactory">DataFactory</h3>

<p>This module should solve problem of generating and populating data for tests. Right now we have <a href="https://codeception.com/docs/modules/Db">Db module</a>, <a href="https://codeception.com/docs/modules/MongoDb">MongoDb</a> with really limited functionality, methods like <code class="language-plaintext highlighter-rouge">haveRecord</code>, <code class="language-plaintext highlighter-rouge">seeRecord</code> in various frameworks, and <a href="https://codeception.com/docs/modules/Sequence">Sequence module</a> for generating unique keys for data. However, they didn’t provide any way to generate data needed exactly for a particular test.</p>

<p>DataFactory module should solve this with fixture generators, called factories. The original idea take from popular Ruby gem <strong>FactoryGirl</strong> and implemented in php in <a href="https://github.com/thephpleague/factory-muffin">FactoryMuffin</a> library, which we use. Laravel 5 users are already aware of using factories. Now you can use them with all PHP frameworks with ActiveRecord pattern and in <strong>Doctrine</strong>.</p>

<p>This is how it works. You define rules to generate models:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="nc">League\FactoryMuffin\Faker\Facade</span> <span class="k">as</span> <span class="nc">Faker</span><span class="p">;</span>

<span class="nv">$fm</span><span class="o">-&gt;</span><span class="nb">define</span><span class="p">(</span><span class="nc">User</span><span class="o">::</span><span class="n">class</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">setDefinitions</span><span class="p">([</span>
 <span class="s1">'name'</span>   <span class="o">=&gt;</span> <span class="nc">Faker</span><span class="o">::</span><span class="nf">name</span><span class="p">(),</span>
    <span class="c1">// generate email</span>
 <span class="s1">'email'</span>  <span class="o">=&gt;</span> <span class="nc">Faker</span><span class="o">::</span><span class="nf">email</span><span class="p">(),</span>
 <span class="s1">'body'</span>   <span class="o">=&gt;</span> <span class="nc">Faker</span><span class="o">::</span><span class="nf">text</span><span class="p">(),</span>

 <span class="c1">// generate a profile and return its Id</span>
 <span class="s1">'profile_id'</span> <span class="o">=&gt;</span> <span class="s1">'factory|Profile'</span>
 <span class="p">]);</span>
</code></pre></div></div>

<p>and DataFactory creates them using underlying ORM, inserts them to database once you call</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">have</span><span class="p">(</span><span class="nc">User</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
</code></pre></div></div>
<p>and deletes them after the test. As we said that will work for Doctrine as well, if you are familiar with Nelmio’s Alice, you might find the same idea but with easier syntax to use.</p>

<h3 id="angularjs">AngularJS</h3>

<p>AngularJS is probably the most popular framework for building single page web applications. It provides its own tool for acceptance testing - <a href="https://angular.github.io/protractor/#/">Protractor</a> but what if you already use Codeception and you are not so passionate to switch to NodeJS? Well if you actually do, please check out our side-project <a href="https://codecept.io">CodeceptJS</a> which brings Codeception concepts to JavaScript world. However, in case of Angular testing there is less reasons to switch, as we brought you Protractor experience in new AngularJS module.</p>

<p>It simply wraps WebDriver module, and adds an asynchronous script between steps to ensure that all client-side operations finished before proceed. This way no new actions are taken before Angular finishes rendering. Also you’ve got new strict locator to use:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'model'</span> <span class="o">=&gt;</span> <span class="s1">'user'</span><span class="p">]);</span>
</code></pre></div></div>

<p>to match elements by their ng-model.</p>

<p>But enough with modules, we have something more than that!</p>

<h3 id="examples">Examples</h3>

<p>In PHPUnit you could have one test to be executed several times with different data, using the data provider mechanism. You can do the same in Codeception inside unit tests. But what about functional and acceptance testing? What if you need to run same scenario but passing different values into it? To be honest, the data provider didn’t looked like an elegant way to define a test data. Data was stored in additional method, often few pages below the original test, so it was hard to see the picture in a whole. We introduce a concept of <code class="language-plaintext highlighter-rouge">Example</code>, similar to what you might have seen in BDD frameworks. Using the <code class="language-plaintext highlighter-rouge">@example</code> annotation you can define data in test annotation and receive from <code class="language-plaintext highlighter-rouge">Codeception\Example</code> instance, injected into test:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
  <span class="cd">/**
   * @example(path=".", file="scenario.suite.yml")
   * @example(path=".", file="dummy.suite.yml")
   * @example(path=".", file="unit.suite.yml")
   */</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">filesExistsAnnotation</span><span class="p">(</span><span class="kt">FileTester</span> <span class="nv">$I</span><span class="p">,</span> <span class="err">\</span><span class="nc">Codeception\Example</span> <span class="nv">$example</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amInPath</span><span class="p">(</span><span class="nv">$example</span><span class="p">[</span><span class="s1">'path'</span><span class="p">]);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeFileFound</span><span class="p">(</span><span class="nv">$example</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]);</span>
  <span class="p">}</span>
<span class="cp">?&gt;</span>
</code></pre></div></div>

<p>For REST API testing this might look like:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
 <span class="cd">/**
  * @example ['/api/', 200]
  * @example ['/api/protected', 401]
  * @example ['/api/not-found-url', 404]
  * @example ['/api/faulty', 500]
  */</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">checkEndpoints</span><span class="p">(</span><span class="kt">ApiTester</span> <span class="nv">$I</span><span class="p">,</span> <span class="err">\</span><span class="nc">Codeception\Example</span> <span class="nv">$example</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendGET</span><span class="p">(</span><span class="nv">$example</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseCodeIs</span><span class="p">(</span><span class="nv">$example</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
  <span class="p">}</span>
<span class="cp">?&gt;</span>
</code></pre></div></div>

<p>Data in <code class="language-plaintext highlighter-rouge">@example</code> annotation can be defined using JSON objects, JSON-arrays, or Symfony-style annotation.
And yes, examples work only in Cests.</p>

<h3 id="custom-commands">Custom Commands</h3>

<p>Long requested feature that finally was implemented by <a href="https://github.com/sd-tm">Tobias Matthaiou</a> allows you to register custom commands to Codeception runner.</p>

<p>If you ever created Symfony Console commands you will be familiar in creating custom commands for Codeception. You migth probably use to have your own template generators, perform data migrations, etc. You can register one as simple as you do it for extension:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">extensions</span><span class="pi">:</span>
    <span class="na">commands</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">MyApp\MyCustomCommand</span><span class="pi">]</span>
</code></pre></div></div>

<h3 id="getting-current-browser-and-capabilities-in-tests">Getting current browser and capabilities in tests</h3>

<p>The last one, simple yet useful thing that might improve your acceptance testing experience. If you want to have different behavior of tests for different browsers, you can get current browser name from a <code class="language-plaintext highlighter-rouge">$scenario-&gt;current</code> value:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'browser'</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'phantomjs'</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// emulate popups for PhantomJS</span>
  <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeScript</span><span class="p">(</span><span class="s1">'window.alert = function(){return true;}'</span><span class="p">);</span> 
<span class="p">}</span>
<span class="cp">?&gt;</span>
</code></pre></div></div>

<p>in a similar manner you have access to all browser capabilities:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$capabilities</span> <span class="o">=</span> <span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'capabilities'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$capabilities</span><span class="p">[</span><span class="s1">'platform'</span><span class="p">]))</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nv">$capabilities</span><span class="p">[</span><span class="s1">'platform'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'Windows'</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// windows specific hooks</span>
  <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span>
</code></pre></div></div>

<hr />

<p>That’s all for today, but not for Codeception 2.2
The most important and most impressive feature is waiting for you in next post. Subscribe to our <a href="https://twitter.com/codeception">Twitter</a>  to not miss it. Stay tuned!</p>
 ]]></description>
    </item>
    
    <item>
      <title>On The Threshold of Codeception 2.2: Upcoming Features</title>
      <link>https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features.html</link>
      <pubDate>Sat, 05 Mar 2016 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-05-2016/codeception-2.2.-upcoming-features</guid>
      <description><![CDATA[ <p>Codeception 2.2 is going to land in nearest weeks. We planned to release it much earlier, but as we are not bound to specific date, we decided to work more on improvements and include the most tasty ones in next release. In this and following blogposts we will review the most significant of upcoming features. So take a look what we prepared for you.</p>

<p>We don’t plan any major breaking changes in this release. However, we will remove deprecations, as you may know we display deprecation warnings in output, so this break should be at least predictable.</p>

<h3 id="phpunit5-support">PHPUnit5 support</h3>

<p>Yes, Codeception is finally will unlock it’s dependency on PHPUnit 4.8 so you could receive the latest stable versions of PHPUnit. As you may know PHPUnit 5.x has much better support of PHP7, so anyone who develop using the latest version of PHP should use it. But wait, it’s not the feature of Codeception 2.2 itself! Codeception 2.1.7 will be released with PHPUnit 5.x support as well.</p>

<h3 id="test-dependencies">Test Dependencies</h3>

<p>Finally <code class="language-plaintext highlighter-rouge">@depends</code> annotation works as you might expected it to. The hardest thing about dependencies is that PHPUnit does nothing to organize dependent tests in a right order:</p>

<blockquote>
  <p>PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers.</p>
</blockquote>

<p>So their usage in Codeception was useless, especially if you were executing tests in random order with <code class="language-plaintext highlighter-rouge">shuffle: true</code> configuration. Some test frameworks, like minitest from Ruby run tests in shuffle by default. On the contrary PHPUnit restricts that, test with <code class="language-plaintext highlighter-rouge">@depends</code> annotation must be be executed after the test it relies on. It actually requires you to declare dependent tests in the same file and use the exact order of test execution.</p>

<p>Codeception takes the exact <code class="language-plaintext highlighter-rouge">@depends</code> annotation, reorders tests so dependent tests always will executed after the tests they rely on. This will work for Cest and Test formats both. And you can actually declare dependencies for tests in other files. Be sure, they will be taken, executed in the right order, and if a test fails its dependencies will be skipped. This is likely improve acceptance testing. If login test doesn’t pass, you shouldn’t even try to launch all other tests with authorization required.</p>

<p>Here is the annotation format to use to declare dependencies. It should be {fullClassName}:{testName} or {testName} for the test in the same class.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@depends login
@depends UserCest:login
@depends App\Service\UserTest:create
</code></pre></div></div>

<p>Unlike PHPUnit, you can’t pass data between dependent tests. Alternatively you can use Helpers or <code class="language-plaintext highlighter-rouge">Codeception\Util\Fixtures</code> class to store shared data.</p>

<h3 id="params">Params</h3>

<p>This lines are written just in the same time as corresponding pull request is merged:</p>

<p><img src="/images/params_screenshot.png" alt="" /></p>

<p>Codeception 2.2 will allow you to use parameter in configuration files populated from environment variables, yaml configs or .env files. You can use parametrized vars in suite configs, by wrapping them in <code class="language-plaintext highlighter-rouge">%</code> placeholder, and adding one or several parameter providers using the <code class="language-plaintext highlighter-rouge">params</code> key in global config:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">params</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">env</span><span class="pi">]</span> <span class="c1"># get prameters from environment vars</span>
</code></pre></div></div>

<p>You can use Symfony-style <code class="language-plaintext highlighter-rouge">.yml</code> files, Laravel-style <code class="language-plaintext highlighter-rouge">.env</code>, or <code class="language-plaintext highlighter-rouge">.ini</code> files to receive params.</p>

<p>This feature would be useful if you want to share database configuration with application and tests. This will especially be useful if you use some sort of credentials passed via environment vars. For instance, if you use cloud testing services, you can set login and password with params and get the real values from environment:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="na">modules</span><span class="pi">:</span>
       <span class="na">enabled</span><span class="pi">:</span>
          <span class="pi">-</span> <span class="na">WebDriver</span><span class="pi">:</span>
             <span class="na">url</span><span class="pi">:</span> <span class="s">http://mysite.com</span>
             <span class="na">host</span><span class="pi">:</span> <span class="s1">'</span><span class="s">%SAUCE_USER%:%SAUCE_KEY%@ondemand.saucelabs.com'</span>
             <span class="na">port</span><span class="pi">:</span> <span class="m">80</span>
             <span class="na">browser</span><span class="pi">:</span> <span class="s">chrome</span>
             <span class="na">capabilities</span><span class="pi">:</span>
                 <span class="na">platform</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Windows</span><span class="nv"> </span><span class="s">10'</span>
</code></pre></div></div>

<h3 id="conflicts">Conflicts</h3>

<p>This is possibly a breaking feature which was announced in Codeception 2.1 but never worked the way it supposed to be. So let’s talk about it once again. A friendly reminder, if you use config like this:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">PhpBrowser</span><span class="pi">,</span> <span class="nv">Laravel5</span><span class="pi">,</span> <span class="nv">WebDriver</span><span class="pi">]</span>
</code></pre></div></div>

<p>you will have problems in Codeception 2.2, if you didn’t have them earlier. Basically the issue here, that those modules provide pretty the same API but different backends for test executions. So it’s hard to tell from config, will this tests be executed as Laravel functional tests, as acceptance tests in real browser, or HTML-scrapper called PhpBrowser. We have lots of issues, when developers misuse those modules, trying to include everything in one config, and we can’t help them besides the good advice to choose one module of one kind.</p>

<p>To avoid this confusion we introduced Conflicts API. Module can declare conflict for modules of the same API, and <code class="language-plaintext highlighter-rouge">ConfigurationException</code> will be thrown if you try to use them in group.</p>

<p>But what if you <em>really</em> need to use Laravel5 module along with, let’s say, WebDriver? Don’t worry, partially loaded modules won’t get into conflict. The most common use case is using Laravel ORM methods to create-delete data for acceptance test. In this case you don’t need to load all actions of Laravel5 module but only those related to ORM:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">WebDriver</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s">http://localhost</span>
            <span class="na">browser</span><span class="pi">:</span> <span class="s">firefox</span>
        <span class="pi">-</span> <span class="na">Laravel5</span><span class="pi">:</span>
            <span class="na">part</span><span class="pi">:</span> <span class="s">orm</span>
</code></pre></div></div>

<p>this way you receive <code class="language-plaintext highlighter-rouge">haveRecord</code>, <code class="language-plaintext highlighter-rouge">seeRecord</code>, <code class="language-plaintext highlighter-rouge">grabRecord</code>, <code class="language-plaintext highlighter-rouge">have</code>, <code class="language-plaintext highlighter-rouge">haveMultiple</code> methods running though Eloquent but <code class="language-plaintext highlighter-rouge">amOnPage</code>, <code class="language-plaintext highlighter-rouge">see</code>, etc will be executed through WebDriver.</p>

<p>If you were mixing WebDriver with PhpBrowser in order to use REST API inside acceptance tests, you can still have it. Don’t enable PhpBrowser but set it as dependent module for REST:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">WebDriver</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s">http://localhost/</span>
            <span class="na">browser</span><span class="pi">:</span> <span class="s">firefox</span>
        <span class="pi">-</span> <span class="na">REST</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s">http://localhost/api</span>
            <span class="na">depends</span><span class="pi">:</span> <span class="s">PhpBrowser</span>
</code></pre></div></div>

<p>This way you can use API to create test data for application:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AcceptanceTester</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="c1">// let's create a post</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendPOST</span><span class="p">(</span><span class="s1">'/posts'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'title'</span> <span class="o">=&gt;</span> <span class="s1">'Hello, Codeception 2.2'</span><span class="p">,</span> <span class="s1">'body'</span> <span class="o">=&gt;</span> <span class="s1">'Almost here'</span><span class="p">]);</span>

<span class="c1">// check it is actually there</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello, Codeception'</span><span class="p">,</span> <span class="s1">'h2'</span><span class="p">);</span>
</code></pre></div></div>

<h3 id="and-much-more-to-come">…and much more to come</h3>

<p>Sure, that was not everything what is coming in 2.2! Stay tuned for new cool announcements, which will be posted soon. We will describe new modules, new test formats, and new features! Stay tuned.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Using Codeception for Symfony Projects</title>
      <link>https://codeception.com/09-04-2015/using-codeception-for-symfony-projects.html</link>
      <pubDate>Fri, 04 Sep 2015 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-04-2015/using-codeception-for-symfony-projects</guid>
      <description><![CDATA[ <p>Codeception Testing Framework from its roots was a plugin of symfony 1 framework. Today Codeception is powered by Symfony components and can be used to run functional tests for practically any popular PHP framework.</p>

<p>Why would you someone ever choose Codeception if Symfony already has mature testing infrastructure. Well, here are our reasons. Codeception tests are:</p>

<ul>
  <li><strong>fast</strong>, as each functional/integration test is wrapped into transaction using Doctrine ORM</li>
  <li><strong>scenario-driven</strong>, it means that tests are linear, described in easy to get PHP DSL</li>
  <li>can be used for <strong>testing complex interactions</strong> inside functional tests.</li>
  <li><strong>easy to write</strong>, as Codeception already provides bundled actions and assertions for most popular use cases.</li>
  <li>combine <strong>all testing levels</strong> (acceptance, functional, unit) in one tool.</li>
</ul>

<p>Today we will write how Codeception can be installed into a Symfony project and fit with its structure: we will put functional and unit tests to corresponding bundles, write acceptance tests for complete application, and use one runner to execute them all at once.</p>

<p><img src="https://farm8.staticflickr.com/7720/17002708897_fb52f39a39_o.png" alt="symfony-demo" /></p>

<p>We will use official <a href="https://symfony.com/blog/introducing-the-symfony-demo-application">symfony-demo</a> application in this example. Once you get it <a href="https://github.com/symfony/symfony-demo#installation">installed</a> you should add Codeception testing framework to dev dependencies list in <code class="language-plaintext highlighter-rouge">composer.json</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:~2.1"</span></code></pre></figure>

<p>As you may know Codeception has <code class="language-plaintext highlighter-rouge">bootstrap</code> command which create common file structure for acceptance, functional, and unit tests. However, as we decided we will follow Symfony way and skip creating global functional and unit tests. So we start with bootstrapping empty project without predefined suites.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept bootstrap <span class="nt">--empty</span></code></pre></figure>

<p>As you may see, we got new <code class="language-plaintext highlighter-rouge">tests</code> directory and <code class="language-plaintext highlighter-rouge">codeception.yml</code> file created. Let’s have acceptance tests there:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept g:suite acceptance</code></pre></figure>

<p>Acceptance tests are expected to test the site from an end-user’s perspective. No matter how many unit tests you have in your projects you can’t get without acceptance testing. What if you see a blank page even all unit tests passed. How could this happen? Maybe you rendered wrong template, maybe some scripts or styles were not loaded. Those things can’t be handled with internal: unit or functional testing, however with acceptance tests you may be confident that UI is available for customers.</p>

<p>That’s why we recommend to have tests with real browser interaction. You can <a href="https://codeception.com/docs/03-AcceptanceTests">learn more about acceptance testing</a> from our guides.</p>

<p>But what about unit and functional tests? As we decided we will put them into bundles. <em>Symfony-demo</em> has only <em>AppBundle</em> included, so we will create new Codeception setup in <code class="language-plaintext highlighter-rouge">src/AppBundle</code>. Take a note that we want those tests to be placed in their own namespace:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept bootstrap <span class="nt">--empty</span> src/AppBundle <span class="nt">--namespace</span> AppBundle</code></pre></figure>

<p>We will also create <code class="language-plaintext highlighter-rouge">unit</code> and <code class="language-plaintext highlighter-rouge">functional</code> suites there:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept g:suite functional <span class="nt">-c</span> src/AppBundle
php bin/codecept g:suite unit <span class="nt">-c</span> src/AppBundle</code></pre></figure>

<p>As you noticed we specify path to different Codeception setup with <code class="language-plaintext highlighter-rouge">-c</code> or <code class="language-plaintext highlighter-rouge">--config</code> option.</p>

<p>Unit tests of Codeception are not quite different from regular PHPUnit tests. You can even copy your old PHPUnit tests to <code class="language-plaintext highlighter-rouge">src/AppBundle/tests/unit</code> and have Codeception run them. It is much more interesting to use Codeception to have functional tests replacing ones extending <code class="language-plaintext highlighter-rouge">Symfony\Bundle\FrameworkBundle\Test\WebTestCase</code> class.</p>

<p>Let’s have a test that will check that there is specific number of posts on a page. Symfony-demo app has the <a href="https://github.com/symfony/symfony-demo/blob/master/src%2FAppBundle%2FTests%2FController%2FBlogControllerTest.php#L29">similar test</a> included:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">AppBundle\Tests\Controller</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Symfony\Bundle\FrameworkBundle\Test\WebTestCase</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">AppBundle\Entity\Post</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">BlogControllerTest</span> <span class="kd">extends</span> <span class="nc">WebTestCase</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">testIndex</span><span class="p">()</span>
  <span class="p">{</span>
      <span class="nv">$client</span> <span class="o">=</span> <span class="k">static</span><span class="o">::</span><span class="nf">createClient</span><span class="p">();</span>
      <span class="nv">$crawler</span> <span class="o">=</span> <span class="nv">$client</span><span class="o">-&gt;</span><span class="nf">request</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">,</span> <span class="s1">'/en/blog/'</span><span class="p">);</span>
      <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertCount</span><span class="p">(</span>
          <span class="nc">Post</span><span class="o">::</span><span class="no">NUM_ITEMS</span><span class="p">,</span>
          <span class="nv">$crawler</span><span class="o">-&gt;</span><span class="nf">filter</span><span class="p">(</span><span class="s1">'article.post'</span><span class="p">),</span>
          <span class="s1">'The homepage displays the right number of posts.'</span>
      <span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>We will rewrite it in Codeception manner. At first we are generating new empty test case for it. We use scenario-driven test format called Cest:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept g:cest functional BlogCest <span class="nt">-c</span> src/AppBundle</code></pre></figure>

<p>And here goes the test:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">AppBundle</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">AppBundle\Entity\Post</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">BlogCest</span> 
<span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">postsOnIndexPage</span><span class="p">(</span><span class="kt">FunctionalTester</span> <span class="nv">$I</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/en/blog/'</span><span class="p">);</span>
        <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeNumberOfElements</span><span class="p">(</span><span class="s1">'article.post'</span><span class="p">,</span> <span class="nc">Post</span><span class="o">::</span><span class="no">NUM_ITEMS</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see, Codeception test is shorter. It is simple, clean, and can be easily extended for more complex interactions. However, we are not ready to run it yet. We need to prepare Codeception to run functional tests inside Symfony context. For this we need to edit <code class="language-plaintext highlighter-rouge">src/AppBundle/tests/functional.yml</code> configuration file to enable modules: <code class="language-plaintext highlighter-rouge">Symfony2</code> and <code class="language-plaintext highlighter-rouge">Doctrine2</code> to use:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">FunctionalTester</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">Symfony2</span><span class="pi">:</span>
            <span class="na">app_path</span><span class="pi">:</span> <span class="s1">'</span><span class="s">../../app'</span>
            <span class="na">var_path</span><span class="pi">:</span> <span class="s1">'</span><span class="s">../../app'</span>
        <span class="pi">-</span> <span class="na">Doctrine2</span><span class="pi">:</span>
            <span class="na">depends</span><span class="pi">:</span> <span class="s">Symfony2</span>
        <span class="pi">-</span> <span class="s">\AcmeBundle\Helper\Functional</span></code></pre></figure>

<p>The most important thing here is to provide valid app and var paths for Symfony. Also we are specifying that Doctrine’s EntityManager should be taken from Symfony DIC. Let’s run functional tests of AppBundle:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept run functional <span class="nt">-c</span> src/AppBundle</code></pre></figure>

<p>In this case you will see following output:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Codeception PHP Testing Framework v2.1.2
Powered by PHPUnit 4.8.2 by Sebastian Bergmann and contributors.

AcmeBundle.functional Tests <span class="o">(</span>1<span class="o">)</span> <span class="nt">------------------------</span>
Posts on index page <span class="o">(</span>BlogCest::postsOnIndexPage<span class="o">)</span>     Ok
<span class="nt">--------------------------------------------------------</span>


Time: 274 ms, Memory: 36.00Mb

OK <span class="o">(</span>1 <span class="nb">test</span>, 1 assertion<span class="o">)</span></code></pre></figure>

<p>But you can do much more with functional testing. You can insert/assert data with Doctrine by using prepared methods like <code class="language-plaintext highlighter-rouge">haveInRepository</code>, <code class="language-plaintext highlighter-rouge">seeInRepository</code> of <a href="https://codeception.com/docs/modules/Doctrine2">Doctrine2</a> module. You can perform complex web interactions like filling forms, clicking links, following redirects and much more with methods of <a href="https://codeception.com/docs/modules/Symfony2">Symfony2</a> module. Those modules are combined together and their methods are available in <code class="language-plaintext highlighter-rouge">FunctionalTester</code> class you are supposed to use for writing functional tests. If you are interested to see more complex Codeception tests, we’ve got <a href="https://github.com/Codeception/symfony-demo/blob/2.1/src%2FAppBundle%2Ftest%2Ffunctional%2FPostCrudCest.php">them for you</a>.</p>

<p>Btw, you can use Symfony2 and Doctrine2 module for writing your unit and integration tests as well.</p>

<hr />

<p>But how can we run acceptance tests of a project with tests from AppBundle together? We need to edit <code class="language-plaintext highlighter-rouge">codeception.yml</code> configuration file in project root to make it. Let’s add those lines there:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">include</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="s">src/*Bundle</span></code></pre></figure>

<p>That’s it. For now Codeception will include all installations stored in Bundles on run. If you execute:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php bin/codecept run</code></pre></figure>

<p>you will probably see that <code class="language-plaintext highlighter-rouge">BlogCest</code> of <code class="language-plaintext highlighter-rouge">AppBundle</code> was executed as it was expected to.</p>

<hr />

<p><img src="https://github.com/Codeception/symfony-demo/raw/2.1/app/data/demo.png" alt="tests" /></p>

<p>The most complex thing in starting using Codeception with Symfony is have it configured. Despite Codeception is auto-connecting to Symfony framework and Doctrine you still have to do some changes to follow Symfony structure. Please <strong>take a detailed look into <a href="https://github.com/Codeception/symfony-demo">our forked version of symfony-demo project</a></strong> 
which we configured in the manner we described in this post. Please use similar configuration for all your Symfony projects.</p>

<p>Start using Codeception and discover how complex things can be tested in really simple manner. And once again, even functional and integration tests are really fast, as we start transaction before each test and rollback it afterwards. Write them as many as you need to, do not rely on unit tests only!</p>

<p><strong>P.S.</strong> Symfony2 and Doctrine2 module is seeking for an active maintainer. If you work with Symfony and Codeception please <a href="https://codeception.com/credits">contact us</a> to join Codeception team!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.1 Is Here</title>
      <link>https://codeception.com/06-30-2015/codeception-2.1-is-here.html</link>
      <pubDate>Tue, 30 Jun 2015 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-30-2015/codeception-2.1-is-here</guid>
      <description><![CDATA[ <p>We are finally ready to show you the Codeception 2.1. Since RC we stabilized its codebase, and we encourage you to start all your new projects with Codeception 2.1. As well as migrate old ones. Codeception 2.1 is aimed for consistency and provide you the better experience for testing your web applications. This new release makes tests even more simple to read, write, and maintain.</p>

<p>If you didn’t track for the changes in master we will list all the new features here:</p>

<ul>
  <li>We added <a href="https://github.com/Codeception/Codeception/tree/master/ext#codeceptionextensionrecorder">Recorder</a> extension, which is probably the most fancy feature you may try. Using it you can record test execution history by saving a screenshot of each step. This is handy for running tests on CI, debugging tests executed via <em>PhantomJS</em> or showing nice reports to your boss.</li>
</ul>

<p><img src="https://codeception.com/images/recorder.gif" alt="recorder" /></p>

<ul>
  <li><strong>Updated to Guzzle 6</strong>. Codeception can now work both with Guzzle v5 and Guzzle v6. PhpBrowser chooses right connector depending on Guzzle version installed.</li>
  <li><strong>PSR-4</strong>: all support classes moved to <code class="language-plaintext highlighter-rouge">tests/_support</code> by default. Actors, Helpers, PageObjects, StepObjects, GroupObjects to follow PSR-4 naming style. New <code class="language-plaintext highlighter-rouge">AcceptanceTester</code>, <code class="language-plaintext highlighter-rouge">FunctionalTester</code>, <code class="language-plaintext highlighter-rouge">UnitTester</code> classes are expected to be extended with methods of common behaviors there. For instance, it is a good idea to place <code class="language-plaintext highlighter-rouge">login</code> method into  the actor class:</li>
</ul>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">AcceptanceTester</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Actor</span>
<span class="p">{</span>
    <span class="kn">use</span> <span class="nc">_generated\AcceptanceTesterActions</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">login</span><span class="p">()</span>
    <span class="p">{</span>
       <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
       <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="s1">'jon'</span><span class="p">);</span>
       <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'password'</span><span class="p">,</span> <span class="s1">'123345'</span><span class="p">);</span>
       <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<ul>
  <li><strong>Dependency Injection</strong>: support classes can be injected into tests. Support classes can be injected into each other too.</li>
</ul>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">UserCest</span> 
<span class="p">{</span>
  <span class="c1">// inject page objects into Cests</span>
  <span class="k">function</span> <span class="n">updatePassword</span><span class="p">(</span><span class="err">\</span><span class="nc">Page\User</span> <span class="nv">$page</span><span class="p">,</span> <span class="nc">AcceptanceTester</span> <span class="nv">$I</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="nv">$page</span><span class="o">-&gt;</span><span class="nf">openProfile</span><span class="p">();</span>
      <span class="nv">$page</span><span class="o">-&gt;</span><span class="nf">editProfile</span><span class="p">();</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$page</span><span class="o">-&gt;</span><span class="n">oldPasswordField</span><span class="p">,</span> <span class="s1">'123456'</span><span class="p">);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$page</span><span class="o">-&gt;</span><span class="n">newPasswordField</span><span class="p">,</span> <span class="s1">'654321'</span><span class="p">);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$page</span><span class="o">-&gt;</span><span class="n">passwordFieldRepeat</span><span class="p">,</span> <span class="s1">'654321'</span><span class="p">);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$page</span><span class="o">-&gt;</span><span class="n">saveBtn</span><span class="p">);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Password has been updated'</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="c1">// inject step object into Cest</span>
  <span class="k">function</span> <span class="n">adminUpdatePassword</span><span class="p">(</span><span class="err">\</span><span class="nc">Step\Admin</span> <span class="nv">$I</span><span class="p">)</span>
  <span class="p">{</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">enterAdminArea</span><span class="p">();</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">changePassword</span><span class="p">(</span><span class="s1">'654321'</span><span class="p">);</span>
      <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Password has been updated'</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<ul>
  <li><strong>Module config simplified</strong>: Modules can be configured in <code class="language-plaintext highlighter-rouge">enabled</code> section of suite config. Take a look of this sample declaration of Api suite, there is no <code class="language-plaintext highlighter-rouge">config</code> section inside modules.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modules:
    enabled:
        - WebDriver:
            url: https://codeception.com
            browser: firefox
        - \Helper\Acceptance
</code></pre></div></div>
<ul>
  <li><strong>Dependencies</strong>: module can explicitly define dependencies and expect their injection. REST, SOAP and Doctrine2 modules rely on another module which should be explicitly set via <code class="language-plaintext highlighter-rouge">depends</code> config param.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class_name: ApiTester
modules:
    enabled:
        - REST:
            url: https://api.github.com/
            depends: PhpBrowser           
        - \Helper\Api
</code></pre></div></div>
<p>As you can see, you don’t need to specify <code class="language-plaintext highlighter-rouge">PhpBrowser</code> in  <code class="language-plaintext highlighter-rouge">enabled</code> section, you can set it only via <code class="language-plaintext highlighter-rouge">depends</code>.</p>

<ul>
  <li>
    <p><strong>Conflicts</strong>: module can define conflicts with each other. Modules that share similar interfaces like <code class="language-plaintext highlighter-rouge">WebDriver</code>, <code class="language-plaintext highlighter-rouge">PhpBrowser</code>, and framework modules won’t run together. You should avoid enabling more than one of those modules in suite config to avoid confusion. If you enable <code class="language-plaintext highlighter-rouge">Laravel5</code> and <code class="language-plaintext highlighter-rouge">WebDriver</code> and execute <code class="language-plaintext highlighter-rouge">$I-&gt;amOnPage('/')</code> you can’t be sure how this command is exected - will it open a browser window using WebDriver protocol, or it will be handled by Laravel framework directly.</p>
  </li>
  <li>
    <p><strong>Current</strong> modules, environment, and test name can be received in scenario.</p>
  </li>
</ul>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'name'</span><span class="p">);</span> <span class="c1">// returns current test name</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'modules'</span><span class="p">);</span> <span class="c1">// returns current modules</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'env'</span><span class="p">);</span> <span class="c1">// returns environment</span>

<span class="c1">// can be used like this</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'env'</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'firefox'</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// do something for firefox only</span>
<span class="p">}</span>
<span class="c1">// naming screenshot</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">makeScreenshot</span><span class="p">(</span><span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nb">current</span><span class="p">(</span><span class="s1">'name'</span><span class="p">)</span><span class="mf">.</span><span class="s1">'_screenshot.png'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<ul>
  <li><strong>Environment Matrix</strong>: You can run tests combining several environments by separating their names by comma:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codecept run --env dev,phantom --env dev,chrome --env dev,firefox
</code></pre></div></div>

<p>Environments can now be stored in separate configuration files in <code class="language-plaintext highlighter-rouge">tests/_envs</code> dir created with <code class="language-plaintext highlighter-rouge">generate:environment</code> command:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tests/_envs
|── chrome.yml
|── phantom.yml
|── firefox.yml
|── dev.yml
</code></pre></div></div>

<ul>
  <li>Cept files should avoid setting their metadata via <code class="language-plaintext highlighter-rouge">$scenario</code> methods. Instead of calling <code class="language-plaintext highlighter-rouge">$scenario-&gt;skip()</code>, <code class="language-plaintext highlighter-rouge">$scenario-&gt;group('firefox')</code>, etc, it is recommended to set scenario settings with annotations <code class="language-plaintext highlighter-rouge">// @skip</code>, <code class="language-plaintext highlighter-rouge">// @group firefox</code>. However, you can use <code class="language-plaintext highlighter-rouge">$scenario-&gt;skip</code> whenever you need to do it on some condition, like</li>
</ul>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="kc">PHP_OS</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'Win'</span><span class="p">)</span> <span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">skip</span><span class="p">()</span>
<span class="cp">?&gt;</span></code></pre></figure>

<ul>
  <li>
    <p>Improved HTML reports
<img src="/images/html-report.png" alt="html report" /></p>
  </li>
  <li>
    <p><strong>Modules can be partially loaded</strong>. If you need only some actions to be included into tester objects. For instance, you want to have REST API tests with Laravel5 module. In this case you probably don’t want methods from Laravel module like <code class="language-plaintext highlighter-rouge">amOnPage</code> or <code class="language-plaintext highlighter-rouge">see</code> to be included into the <code class="language-plaintext highlighter-rouge">ApiTester</code> as they interact with HTML pages, which we are not supposed to use. But you still need Laravel ORM methods like <code class="language-plaintext highlighter-rouge">seeRecord</code> to verify that changes were saved to database. In this case you can enable only ORM methods of Laravel5 module.</p>
  </li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modules:
    enabled: 
        - Laravel5:
            part: ORM
        - REST:
            part: Json
            depends: Laravel5
</code></pre></div></div>

<p>As for REST module you can load methods only for API format you are using. You can choose either XML or Json, so only methods for Json or XML will be loaded.</p>

<ul>
  <li>Whenever you have steps grouped inside actor class, pageobject, or stepobject, you can the step executed with its substeps in console or HTML report. 
<img src="/images/substeps.png" alt="html report" /></li>
  <li><strong>RunFailed</strong> extension is enabled by default for all new projects. It means that you can rerun your failed tests by executing <code class="language-plaintext highlighter-rouge">codecept run -g failed</code> when this extension is enabled. 1</li>
</ul>

<p>And lots of other notable improvements which you can see in <a href="https://github.com/Codeception/Codeception/blob/master/CHANGELOG.md">changelog</a>.</p>

<p>Starting from Codeception 2.1 we <strong>recommend using Cest</strong> as a default format for all scenario-driven acceptance and functional, or api tests. Guides were rewritten to reflect new improved approaches to testing that you should practice by using Codeception.</p>

<h2 id="upgrading">Upgrading</h2>

<ul>
  <li>It is pretty easy to upgrade from 2.0. The only thing you should start with is to rebuild your actor classes by running <code class="language-plaintext highlighter-rouge">codecept build</code> command. The old actor classes (<code class="language-plaintext highlighter-rouge">*Tester</code> or <code class="language-plaintext highlighter-rouge">*Guy</code>) in suite directories should be deleted manually.</li>
  <li>REST, SOAP, Doctrine2 module will need to be configured to use a dependent module as it was shown above. You will get a detailed exception with configuration example once you execute tests with those modules.</li>
  <li>Helpers, PageObjects, StepObjects are expected to follow PSR-4 standard and use namespaces. It is recommended to rename classes to replace suffixes with namespaces, like <code class="language-plaintext highlighter-rouge">UserPage</code> =&gt; <code class="language-plaintext highlighter-rouge">Page\User</code>. However, those changes are <strong>not required</strong>, so you can keep your support objects without changes.</li>
</ul>

<hr />

<p>If you are using 2.0 and you won’t plan to upgrade in nearest future, you can still use releases from 2.0 branch. Minor fixes and improvements will still be accepted there. Also the site will contain documentation for 2.0 and 2.1 versions.</p>

<p>Try Codeception 2.1 today by installing it via Composer:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require "codeception/codeception:*" --dev
</code></pre></div></div>

<p>or by downloading it as <a href="https://codeception.com/codecept.phar">Phar archive</a></p>

<p>And provide a feedback!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.1 RC</title>
      <link>https://codeception.com/06-19-2015/codeception-2.1-rc.html</link>
      <pubDate>Fri, 19 Jun 2015 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-19-2015/codeception-2.1-rc</guid>
      <description><![CDATA[ <p>Today we are announcing Codeception 2.1 RC release. We are almost ready to release a stable version, however we’d like to receive more feedback before the actual launch. We encourage you to install the latest 2.1 release and try it on your projects. Migrations should be painless if you follow the upgrade instructions. Here are the things you should keep in mind while upgrading:</p>

<ul>
  <li>REST, SOAP and Doctrine2 modules rely on another module which should be explicitly set via <code class="language-plaintext highlighter-rouge">depends</code> config param. For instance, you should pass <code class="language-plaintext highlighter-rouge">Laravel5</code> module if you do API testing with <code class="language-plaintext highlighter-rouge">REST</code> module</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modules:
    enabled: [REST, Laravel5]
    config:
        REST:
            depends: Laravel5
</code></pre></div></div>

<ul>
  <li>Actor classes are moved to <code class="language-plaintext highlighter-rouge">_support</code> directory. Please <strong>delete all previously generated actor classes</strong> which reside in suites directories. New <code class="language-plaintext highlighter-rouge">AcceptanceTester</code>, <code class="language-plaintext highlighter-rouge">FunctionalTester</code>, <code class="language-plaintext highlighter-rouge">UnitTester</code> classes are expected to be extended with custom methods.</li>
  <li>Modules that share similar interfaces like <code class="language-plaintext highlighter-rouge">WebDriver</code>, <code class="language-plaintext highlighter-rouge">PhpBrowser</code>, and framework modules won’t run together. You should avoid enabling more than one of those modules in suite config to avoid confusion. If you enable <code class="language-plaintext highlighter-rouge">Laravel5</code> and <code class="language-plaintext highlighter-rouge">WebDriver</code> and execute <code class="language-plaintext highlighter-rouge">$I-&gt;amOnPage('/')</code> you can’t be sure how this command is exected - will it open a browser window using WebDriver protocol, or it will be handled by Laravel framework directly.</li>
  <li>Cept files should avoid setting their metadata via <code class="language-plaintext highlighter-rouge">$scenario</code> methods. Instead of calling <code class="language-plaintext highlighter-rouge">$scenario-&gt;skip()</code>, <code class="language-plaintext highlighter-rouge">$scenario-&gt;group('firefox')</code>, etc, it is recommended to set scenario settings with annotations <code class="language-plaintext highlighter-rouge">// @skip</code>, <code class="language-plaintext highlighter-rouge">// @group firefox</code>. With this change you can now skip tests based on a condition: <code class="language-plaintext highlighter-rouge">if (substr(PHP_OS, 0, 3) == 'Win') $scenario-&gt;skip()</code>.</li>
  <li>Kohana, Symfony1, Doctrine1 modules were removed and they reside in separate repositories in <a href="https://github.com/Codeception">Codeception organization</a> on GitHub.</li>
</ul>

<p>That should be enough to have everything upgraded. We already prepared <a href="https://github.com/Codeception/Codeception/tree/master/docs">updated guides</a> (they didn’t change from 2.1.0-beta). Please try new Codeception and tell us your opinion in comments or on <a href="https://github.com/Codeception/Codeception/issues">GitHub</a>.</p>

<p>Codeception 2.1 can be used with latest Guzzle 6 (as well as previous Guzzle releases). That’s the most important change since the beta version. See <a href="https://github.com/Codeception/Codeception/blob/master/CHANGELOG.md">the changelog</a> for more info. We are preparing site updates and demo apps to reflect new changes. Stay tuned!</p>

<p><a href="https://codeception.com/releases/2.1.0-rc1/codecept.phar">Download 2.1.0-rc phar</a></p>

<p>via <code class="language-plaintext highlighter-rouge">composer.json</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"codeception/codeception": "2.1.0-rc1"
</code></pre></div></div>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.1 Beta</title>
      <link>https://codeception.com/05-02-2015/codeception-2.1-beta.html</link>
      <pubDate>Sat, 02 May 2015 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-02-2015/codeception-2.1-beta</guid>
      <description><![CDATA[ <p>We are glad to announce the first release of Codeception 2.1. It was a long time of developing the next major version of our testing framework. We delayed the release many times trying to bring as many cool features as we could. Today we can say that master branch is stabilized and we are prepared to share results of our work with you. Codeception 2.1 tries to do its best in test codebase organizing, improving ux, and customization.</p>

<p><a href="https://codeception.com/slides/codecept21">Take a look</a> what is landed in Codeception 2.1.</p>

<script async="" class="speakerdeck-embed" data-id="aa35edd4591343369f634ce29944134d" data-ratio="1.41436464088398" src="//speakerdeck.com/assets/embed.js"></script>

<p>Full list of features is available in <a href="https://github.com/Codeception/Codeception/blob/master/CHANGELOG.md#210-beta">changelog</a>. <a href="https://github.com/Codeception/Codeception/pull/1878/files?diff=unified">Documentation was updated</a> accordingly.</p>

<p>You can install Codeception 2.1 via composer by requiring <code class="language-plaintext highlighter-rouge">2.1.0-beta</code> version, or by <a href="/releases/2.1.0-beta/codecept.phar">downloading phar</a>.</p>

<p>Give new Codeception a try and send us feedback. As always <a href="https://github.com/Codeception/Codeception/issues">use GitHub issues</a> for that. Thanks for being with us all that time! We hope you will love this release.</p>

<p>Stable 2.1.0 is expected by the middle-end of May</p>

<h2 id="upgrade-notes">Upgrade Notes</h2>

<ul>
  <li>If you are upgrading from Codeception 2.0 delete actor classes in <code class="language-plaintext highlighter-rouge">tests/acceptance</code>, <code class="language-plaintext highlighter-rouge">tests/functional</code>, etc, and rebuild actor classes. They will be recreated in <code class="language-plaintext highlighter-rouge">tests/_support</code>.</li>
  <li>Try to execute new tests. If there are unmet dependencies, or module conflicts, you will be notified by exception with an advice how to resolve it.</li>
  <li>It is recommended to recreate Helpers per suite with <code class="language-plaintext highlighter-rouge">g:helper</code> generator, like <code class="language-plaintext highlighter-rouge">codecept g:helper Acceptance</code>. New helpers will be store in <code class="language-plaintext highlighter-rouge">tests/_support/Helper</code>.</li>
  <li>Same for PageObjects and StepObjects, they should be moved to <code class="language-plaintext highlighter-rouge">_support</code>.</li>
</ul>
 ]]></description>
    </item>
    
    <item>
      <title>Setting up Jenkins with Codeception</title>
      <link>https://codeception.com/02-04-2015/setting-up-jenkins-with-codeception.html</link>
      <pubDate>Wed, 04 Feb 2015 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-04-2015/setting-up-jenkins-with-codeception</guid>
      <description><![CDATA[ <p><img src="/images/jenkins/Jenk1.png" alt="Jenkins" /></p>

<p>A frequent question that appear from time to time is How to set up Codeception with <a href="https://jenkins-ci.org/">Jenkins</a>. Despite the growth of popularity of various Continuous Integration solutions Jenkins is still the most popular open-source solution on market. It is easy to setup and is easy to customize by applying various 3rd-party plugins. In this post we will take a look on how to setup testing process of <strong>PHP project with Jenkins CI and Codeception</strong>.</p>

<p><img src="/images/jenkins/Jenk2.png" alt="Create new job in Jenkins" /></p>

<h2 id="preparing-jenkins">Preparing Jenkins</h2>

<p>We will start from an empty Jenkins Server executed on localhost. Let’s create a new Job for project tested with Codeception and name it   PHPCodeceptionProject. Before we proceed to configuring it, lets install required plugins:</p>

<ul>
  <li><strong>Git Plugin</strong> - for building tests for Git repo</li>
  <li><strong>Green Balls</strong> - to display success results in green.</li>
  <li><strong>xUnit Plugin</strong>, <strong>jUnit Plugin</strong> - to process and display Codeception XML reports</li>
  <li><strong>HTML Publisher Plugin</strong> - to process Codeception HTML reports</li>
  <li><strong>AnsiColor</strong> - to show colorized console output.</li>
</ul>

<p><img src="/images/jenkins/Jenk3.png" alt="Jenkins Plugins" /></p>

<h2 id="basic-setup">Basic Setup</h2>

<p>Once everything is installed lets get back to configuring our newly created PHPCodeceptionProject. At first we will set up Git to checkout code and build. Depending on your needs you can set up periodical build or trigger build once the change is pushed to GitHub (you will need GitHub plugin for that). You may also set up <strong>Jenkins as alternative to Travis CI</strong> to build your pull requests with <code class="language-plaintext highlighter-rouge">GitHub pull request builder plugin</code>.</p>

<p>We will enable colors in console using Ansi Color</p>

<p><img src="/images/jenkins/Jenk4.png" alt="Jenkins ANSI color" /></p>

<p>Next and the most important part is to define build step. We won’t create any sofisticated environment settings like setting up database and services. We assume that all we need to execute tests is to inctall composer dependencies and run codeception tests:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer <span class="nb">install</span>
./vendor/bin/codecept run</code></pre></figure>

<p><img src="/images/jenkins/Jenk5.png" alt="Jenkins Codeception Build Step" /></p>

<p>And that’s the absolute minimum we need to execute tests in Jenkins. We can save project and execute the job. Jenkins will clone repository from Git, install composer dependencies and run Codeception tests. If tests fail you can review the console output to discover what went wrong.</p>

<p><img src="/images/jenkins/Jenk6.png" alt="Jenkins Console Output" /></p>

<h2 id="xml-reports">XML Reports</h2>

<p>But we don’t want to analyze console output for each failing build. Especially If Jenkins can collect and display the results inside its web UI. Codeception can export its results using JUnit XML format. To generate XML report on each build we will need to append <code class="language-plaintext highlighter-rouge">--xml</code> option to Codeception execution command. Codeception will print <code class="language-plaintext highlighter-rouge">result.xml</code> file containing information about test status with steps and stack traces for failing tests. Unfortunately Jenkins can’t process such special like Codeception steps. So we will need to configure to print data only which strictly applies to xUnit xml format. This should be done in <code class="language-plaintext highlighter-rouge">codeception.yml</code></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">settings</span><span class="pi">:</span>
    <span class="na">strict_xml</span><span class="pi">:</span> <span class="no">true</span></code></pre></figure>

<p>Now let’s update our build step to generate xml:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer <span class="nb">install</span>
./vendor/bin/codecept run <span class="nt">--xml</span></code></pre></figure>

<p>and ask Jenkins to collect resulted XML. This can be done as part of Post-build actions. Let’s add <em>Publish xUnit test result report</em> action and configure it to use with PHPUnit reports.</p>

<p><img src="/images/jenkins/Jenk7.png" alt="Use PHPUnit xUnit builder for Jenkins" /></p>

<p>Now we should specify path to PHPUnit style XML reports. In case of standard Codeception setup we should specify <code class="language-plaintext highlighter-rouge">tests/_output/*.xml</code> as a pattern for matching resulted XMLs. Now we save the project and rebuild it.</p>

<p><img src="/images/jenkins/Jenk8.png" alt="Jenkins Result Trend" /></p>

<p>Now for all builds we will see results trend graph that shows us percentage of passing and failing tests. We also will see a <strong>Latest Test Result</strong> link which will lead to to the page where all executed tests and their stats listed in a table.</p>

<h2 id="html-reports">HTML Reports</h2>

<p>To get more details on steps executed you can ask Codeception to generate HTML report. Jenkins can display them as well.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer <span class="nb">install</span>
./vendor/bin/codecept run <span class="nt">--html</span></code></pre></figure>

<p>Now we need HTML Publisher plugin configured to display generated HTML files. It should be added as post-build action similar way we did it for XML reports.</p>

<p><img src="/images/jenkins/Jenk9.png" alt="Jenkins Codeception HTML Setup" /></p>

<p>Jenkins should locate <code class="language-plaintext highlighter-rouge">report.html</code> located at <code class="language-plaintext highlighter-rouge">tests/_output/</code>. Now Jenkins will display HTML reports for each build.</p>

<p><img src="/images/jenkins/Jenki10.png" alt="Jenkins HTML Report" />
<img src="/images/jenkins/Jenki11.png" alt="Jenkins Codeception HTML Results" /></p>

<p>That’s pretty much everything you need to get a simple Jenkins setup with Codeception.</p>

 ]]></description>
    </item>
    
    <item>
      <title>Acceptance Testing With No Selenium or PhantomJS Installed</title>
      <link>https://codeception.com/11-14-2014/dockerizing-acceptance-testing.html</link>
      <pubDate>Fri, 14 Nov 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-14-2014/dockerizing-acceptance-testing</guid>
      <description><![CDATA[ <p><img src="https://www.seleniumhq.org/images/big-logo.png" alt="Selenium" />
<img src="https://cdn.tutsplus.com/net/uploads/legacy/2161_phantom/preview.png" alt="PhantomJS" /></p>

<p>This post summarizes some recent work that was done for creating portable testing environments. The idea was to reduce dependencies required by acceptance testing. As you know, testing of web pages require Selenium or PhanromJS servers, which allow to interact with web page, and execute user scripts on page. However, installing those dependencies, can be a pain. Especially Selenium. If you are not running it inside desktop environment you probably need to have Firefox or Chromium, and they can’t be run without virtual framebuffer, as they have some display server to run on. Setting up those packages can take liters of sweat and bunch of nerves.</p>

<p>That’s why we decided to pack <strong>Selenium and PhantomJS into portable Docker containers</strong>. Did you hear about <a href="https://docker.com">Docker</a>? If not - you probably should take some time to look at it. Docker allows you to create virtual environments on Linux hosts without real virtualization. Docker creates an isolated environment inside the host machine without recreating operating system.</p>

<p>Docker containers are lightweight and easy to use. If you have Linux. Probably all your servers use Linux, so you might find docker images of Selenium and PhantomJS pretty useful!</p>

<h3 id="seleniumenv-selenium-xvfb-firefox-and-chromium-inside-container"><a href="https://github.com/Codeception/SeleniumEnv">SeleniumEnv</a>: Selenium, Xvfb, Firefox, and Chromium Inside Container</h3>

<p>OK, lets assume <strong>you are using Linux and Docker &gt;=1.2</strong>. 
From now on running Selenium won’t take from you anything more then running those commands:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">docker run <span class="nt">-i</span> <span class="nt">-t</span> <span class="nt">-p</span> 4444:4444 davert/selenium-env</code></pre></figure>

<p>This will start virtual display server (Xvfb) and Selenium inside a container. Please note, you don’t need anything of those installed on your host. Not even Java, required to run Selenium. Only Docker is needed and you can run Selenium in one line!</p>

<p>By running this command you will see this output:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Running Selenium Env: Selenium Server, and Xvfb with Firefox and Chromium
Host IP: 172.17.42.1
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/cyrillic, removing from list!
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/100dpi/:unscaled, removing from list!
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/75dpi/:unscaled, removing from list!
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/Type1, removing from list!
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/100dpi, removing from list!
<span class="o">[</span>dix] Could not init font path element /usr/share/fonts/X11/75dpi, removing from list!
<span class="o">[</span>dix] Could not init font path element /var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType, removing from list!
02:02:30.641 INFO - Launching a standalone server
02:02:30.670 INFO - Java: Oracle Corporation 24.60-b09
02:02:30.670 INFO - OS: Linux 3.16.0-24-generic amd64
02:02:30.684 INFO - v2.44.0, with Core v2.44.0. Built from revision 76d78cf
02:02:30.735 INFO - Default driver org.openqa.selenium.ie.InternetExplorerDriver registration is skipped: registration capabilities Capabilities <span class="o">[{</span><span class="nv">platform</span><span class="o">=</span>WINDOWS, <span class="nv">ensureCleanSession</span><span class="o">=</span><span class="nb">true</span>, <span class="nv">browserName</span><span class="o">=</span>internet explorer, <span class="nv">version</span><span class="o">=}]</span> does not match with current platform: LINUX
02:02:30.790 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
02:02:30.791 INFO - Version Jetty/5.1.x
02:02:30.792 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
02:02:30.792 INFO - Started HttpContext[/selenium-server,/selenium-server]
02:02:30.793 INFO - Started HttpContext[/,/]
02:02:30.806 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@1a966bcb
02:02:30.807 INFO - Started HttpContext[/wd,/wd]
02:02:30.809 INFO - Started SocketListener on 0.0.0.0:4444
02:02:30.809 INFO - Started org.openqa.jetty.jetty.Server@2b6ea258</code></pre></figure>

<p>By specifying <code class="language-plaintext highlighter-rouge">-p 4444:4444</code> option in <code class="language-plaintext highlighter-rouge">docker run</code> we mapped container’s port 4444, which is default for Selenium to the same port on our host machine. So, any process can connect to Selenium on its standard port, even Selenium is completely isolated from other processes.</p>

<p>And here comes a tricky question. If Selenium is completely isolated, how can we test applications running on a local web server? We have a solution for that. If your application is served by nginx or any other web server, you can probably access it by hostname (other than localhost). What we can do is to pass hostname inside a container.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">docker run <span class="nt">-i</span> <span class="nt">-t</span> <span class="nt">-p</span> 4444:4444 <span class="nt">-e</span> <span class="nv">APP_HOST</span><span class="o">=</span>myhost davert/selenium-env</code></pre></figure>

<p>This will bind <code class="language-plaintext highlighter-rouge">myhost</code> to your host machine IP. So, container, and Firefox, Chromium, can get access to your local web site from inside container.</p>

<p>Similar idea is used for application executed on specific port. If you use PHP built-in server, you can start it at specific port, and pass it into container as well. Please note, that to make server accessible from container, it should be started on <code class="language-plaintext highlighter-rouge">0.0.0.0</code> IP:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php <span class="nt">-S</span> 0.0.0.0:8000
<span class="c"># in new terminal window</span>
docker run <span class="nt">-i</span> <span class="nt">-t</span> <span class="nt">-p</span> 4444:4444 <span class="nt">-e</span> <span class="nv">APP_PORT</span><span class="o">=</span>8000 davert/selenium-env 
<span class="c"># in new terminal window</span>
codecept run acceptance</code></pre></figure>

<h3 id="phantomjsenv-phantomjs-inside-container"><a href="https://github.com/Codeception/PhantomJsEnv">PhantomJsEnv</a>: PhantomJS Inside Container</h3>

<p>Instructions are the same for <strong>running PhantomJS</strong>. It can be started with</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">docker run <span class="nt">-i</span> <span class="nt">-t</span> <span class="nt">-p</span> 4444:4444 davert/phantomjs-env</code></pre></figure>

<p>Everything else is pretty similar. Also you can easily switch from Selenium to PhantomJS by starting or stopping those two containers. Isn’t that useful?</p>

<h2 id="images-and-source-code">Images and Source Code</h2>

<p><a href="https://github.com/Codeception/SeleniumEnv">SeleniumEnv</a> and <a href="https://github.com/Codeception/PhantomJsEnv">PhantomJsEnv</a> are created from <a href="https://github.com/travis-ci/travis-cookbooks">Travis CI Cookbooks</a> and packed into containers. They are free to use and free to modify for custom needs.</p>

<p>If you need to have Selenium Server from version other than 2.44.0 (which is latest for today), you should update Docker file and build an image from it.</p>

<p>SeleniumEnv and PhantomJsEnv may simplify testing for all Linux users. They will definitely simplify setting up Continuous Integration servers. You can even <strong>recreate a complete testing environment inside a container</strong>. Take a look into <a href="https://github.com/Codegyre/RoboCI">RoboCI</a> project for this. It allows you to build Travis CI-like service on your own host!</p>

<p>Use them and enjoy :)</p>

<p>P.S. Feedback, Pull Requests, and Issues, are welcome )</p>
 ]]></description>
    </item>
    
    <item>
      <title>Managing Data with FactoryMuffin</title>
      <link>https://codeception.com/10-23-2014/managing-data-with-factorymuffin.html</link>
      <pubDate>Thu, 23 Oct 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-23-2014/managing-data-with-factorymuffin</guid>
      <description><![CDATA[ <p>One of the greatest things of testing Ruby on Rails applications was usage of Factories, managed by <a href="https://github.com/thoughtbot/factory_girl">FactoryGirl</a>. It changed the way the test data was managed in test. Instead of defining fixtures one by one, in a single <code class="language-plaintext highlighter-rouge">.yml</code> configuration, it allowed to generate required models per test. This concept is very convenient, however it is not widespread in PHP world. Probably, this was because, there is no single ORM in PHP, like ActiveRecord is for Ruby. We have Doctrine, Eloquent, and each major framework has its own ORM layer, so that we it is pretty hard to deal with models of those frameworks in one manner.</p>

<p>But it looks like factories finally came to PHP! <a href="https://thephpleague.com/">The League of Extraordinary Packages</a> produced a great package, self-claimed as factory_girl for PHP. Meet <a href="https://factory-muffin.thephpleague.com/">Factory Muffin</a>. It allows simple generation of database records for integration and functional testing. Let’s see how it can be used with Codeception.</p>

<h2 id="setup-in-codeception">Setup in Codeception</h2>

<p>At first lets add <code class="language-plaintext highlighter-rouge">league/factory-muffin": "~2.0</code> to <code class="language-plaintext highlighter-rouge">composer.json</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="s2">"require-dev"</span>: <span class="o">{</span>
    <span class="s2">"codeception/codeception"</span>: <span class="s2">"~2.0"</span>,
    <span class="s2">"league/factory-muffin"</span>: <span class="s2">"~2.0"</span>
<span class="o">}</span></code></pre></figure>

<p>Then we execute <code class="language-plaintext highlighter-rouge">composer install</code>.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Loading composer repositories with package information
Updating dependencies <span class="o">(</span>including require-dev<span class="o">)</span>
  - Installing fzaninotto/faker <span class="o">(</span>v1.4.0<span class="o">)</span>
    Downloading: 100%         

  - Installing league/factory-muffin <span class="o">(</span>v2.1.1<span class="o">)</span>
    Downloading: 100%         

Writing lock file
Generating autoload files
Generating optimized class loader</code></pre></figure>

<p>As you may noticed, FactoryMuffin uses awesome <a href="https://github.com/fzaninotto/Faker">Faker</a> library for generating random data for models.</p>

<p>For using factories inside tests we will create <code class="language-plaintext highlighter-rouge">FactoryHelper</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php vendor/bin/codecept g:helper Factory
Helper /home/davert/project/tests/_support/FactoryHelper.php created</code></pre></figure>

<p>We will define factories in the <code class="language-plaintext highlighter-rouge">_initialize</code> method of <code class="language-plaintext highlighter-rouge">FactoryHelper</code>.
Let’s say we have two models, <code class="language-plaintext highlighter-rouge">Post</code> and <code class="language-plaintext highlighter-rouge">User</code> in application. This is how we specify rules for generating new objects of these models.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">FactoryHelper</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Module</span>
<span class="p">{</span>
    <span class="cd">/**
     * @var \League\FactoryMuffin\Factory
     */</span>
    <span class="k">protected</span> <span class="nv">$factory</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nc">League\FactoryMuffin\Factory</span><span class="p">;</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nb">define</span><span class="p">(</span><span class="s1">'Post'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">'title'</span>    <span class="o">=&gt;</span> <span class="s1">'sentence|5'</span><span class="p">,</span> <span class="c1">// title with random 5 words</span>
            <span class="s1">'body'</span>   <span class="o">=&gt;</span> <span class="s1">'text'</span><span class="p">,</span> <span class="c1">// random text</span>
        <span class="p">));</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nb">define</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">'email'</span> <span class="o">=&gt;</span> <span class="s1">'unique:email'</span><span class="p">,</span> <span class="c1">// random unique email</span>
        <span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This is how generation of Post and User is defined. From the box, Muffin is designed to work with ActiveRecord models, and with Eloquent in particular. So you can use it in Yii, Phalcon, yet we will <strong>demonstrate its usage in Laravel application</strong>. FactoryMuffin can also be customized to work with Doctrine as well.</p>

<h2 id="using-factories-in-laravel">Using Factories in Laravel</h2>

<p>To use FactoryMuffin in Laravel functional tests we need to create additional methods in <code class="language-plaintext highlighter-rouge">FactoryHelper</code> for generating and saving records: <code class="language-plaintext highlighter-rouge">havePosts</code> and <code class="language-plaintext highlighter-rouge">haveUsers</code> methods. They will populate database with number of records specified. We will need to clean up those records at the end of a test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">FactoryHelper</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Module</span>
<span class="p">{</span>
    <span class="cd">/**
     * @var \League\FactoryMuffin\Factory
     */</span>
    <span class="k">protected</span> <span class="nv">$factory</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nc">League\FactoryMuffin\Factory</span><span class="p">;</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nb">define</span><span class="p">(</span><span class="s1">'Post'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">'title'</span>    <span class="o">=&gt;</span> <span class="s1">'sentence|5'</span><span class="p">,</span> <span class="c1">// title with random 5 words</span>
            <span class="s1">'body'</span>   <span class="o">=&gt;</span> <span class="s1">'text'</span><span class="p">,</span> <span class="c1">// random text</span>
        <span class="p">));</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nb">define</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">'email'</span> <span class="o">=&gt;</span> <span class="s1">'unique:email'</span><span class="p">,</span> <span class="c1">// random unique email</span>
        <span class="p">));</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">havePosts</span><span class="p">(</span><span class="nv">$num</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nf">seed</span><span class="p">(</span><span class="nv">$num</span><span class="p">,</span> <span class="s1">'Post'</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">haveUsers</span><span class="p">(</span><span class="nv">$num</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nf">seed</span><span class="p">(</span><span class="nv">$num</span><span class="p">,</span> <span class="s1">'Post'</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">_after</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\TestCase</span> <span class="nv">$test</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// actually this is not needed</span>
        <span class="c1">// if you use cleanup: true option </span>
        <span class="c1">// in Laravel4 module</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nf">deleteSaved</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>By including FactoryHelper to the functional suite config, we can use it inside the actor (<code class="language-plaintext highlighter-rouge">$I</code>) object.</p>

<p>This allows us to test features like pagination. For instance, we can check that only 20 posts are listed on a page:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FunctionalTester</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'check that only 20 posts are listed'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">havePosts</span><span class="p">(</span><span class="mi">40</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeNumberOfElements</span><span class="p">(</span><span class="s1">'.post'</span><span class="p">,</span> <span class="mi">20</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><a href="https://github.com/Codeception/sample-l4-app/commit/7057518d41eaff6bbba2d4bea7aee400cf504492">Source code of this example is on GitHub</a>.</p>

<h2 id="factories-in-unit-tests">Factories in Unit Tests</h2>

<p>Factories can also be used in unit testing. Let’s say user can create posts, and in order to optimize queries we are saving number of user posts in <code class="language-plaintext highlighter-rouge">num_posts</code> column of <code class="language-plaintext highlighter-rouge">users</code> table. We are going to test that this column is updated each time a new post by user is created.</p>

<p>We will need one more method added into <code class="language-plaintext highlighter-rouge">FactoryHelper</code> class:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">produce</span><span class="p">(</span><span class="nv">$model</span><span class="p">,</span> <span class="nv">$attributes</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">factory</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">(</span><span class="nv">$model</span><span class="p">,</span> <span class="nv">$attributes</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>After we include <code class="language-plaintext highlighter-rouge">FactoryHelper</code> into unit suite we can use its methods in tests:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">UserTest</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\TestCase\Test</span>
<span class="p">{</span>
    <span class="cd">/**
     * @var UnitTester
     */</span>
    <span class="k">protected</span> <span class="nv">$tester</span><span class="p">;</span>

    <span class="k">function</span> <span class="n">testCounterCache</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$user</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">produce</span><span class="p">(</span><span class="s1">'User'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="n">num_posts</span><span class="p">);</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">produce</span><span class="p">(</span><span class="s1">'Post'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'user_id'</span> <span class="o">=&gt;</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">]);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nc">User</span><span class="o">::</span><span class="nf">find</span><span class="p">(</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">num_posts</span><span class="p">);</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">produce</span><span class="p">(</span><span class="s1">'Post'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'user_id'</span> <span class="o">=&gt;</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">]);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nc">User</span><span class="o">::</span><span class="nf">find</span><span class="p">(</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">num_posts</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="conclusion">Conclusion</h2>

<p>As you see, factories make your tests clean and expressive. 
Forget about managing test data manually, forget about fixtures. Use <a href="https://factory-muffin.thephpleague.com/">FactoryMuffin</a>.</p>

<p><strong>Update</strong> <a href="https://github.com/DavertMik/SymfonyCodeceptionApp/blob/factories/tests/_support/FactoryHelper.php">FactoryHelper for Symfony2 and Doctrine modules</a></p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception Updates</title>
      <link>https://codeception.com/10-12-2014/codeception-updates.html</link>
      <pubDate>Sun, 12 Oct 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-12-2014/codeception-updates</guid>
      <description><![CDATA[ <p>Codeception is improving from day to day with the help of our contributors. Recently we had new 2.0.6 release with lots of bugfixes and new features. Unfortunately some not obvious regressions were introduced, and we had to release 2.0.7 as fast as we could.</p>

<p>In order to maintain a predictable release cycle we plan to release a new <strong>bugfix version each month</strong> and deliver a <strong>new major version each 6 months</strong>. We tend to follow this plan for future, yet we are not ready to follow it strictly.</p>

<p>Today we have a few more announcements to sum up all recent work on Codeception and its support projects.</p>

<h2 id="codecoverage">CodeCoverage</h2>

<p>Latest updates to <a href="https://github.com/Codeception/c3">c3</a> brought full compatibility with Codeception 2.0. Also c3 can be installed and updated via Composer.</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="nl">"require-dev"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"codeception/c3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.*"</span><span class="w">
</span><span class="p">}</span><span class="err">,</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"post-install-cmd"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"Codeception</span><span class="se">\\</span><span class="s2">c3</span><span class="se">\\</span><span class="s2">Installer::copyC3ToRoot"</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"post-update-cmd"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="s2">"Codeception</span><span class="se">\\</span><span class="s2">c3</span><span class="se">\\</span><span class="s2">Installer::copyC3ToRoot"</span><span class="w">
    </span><span class="p">]</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>This allows to follow updates of code coverage collector (c3) easily. Also please note, that c3 issues were moved to main Codeception repo.</p>

<h2 id="aspectmock">AspectMock</h2>

<p><a href="https://github.com/Codeception/AspectMock">AspectMock</a> was recently updated to version 0.5.0. Latest update is powered by <a href="https://github.com/lisachenko/go-aop-php">Go Aop framework</a> version 0.5. In new AspectMock fixed passing parameters by reference, and added ability to mock PHP functions.</p>

<p>AspectMock allows to replace PHP function in desired namespace with user-defined closure or a return single return value. For instance, you can stub file operations by mocking <code class="language-plaintext highlighter-rouge">file_get_contents</code> or <code class="language-plaintext highlighter-rouge">file_put_contents</code>. You can also mock time functions, in order to make tests stable to time changes.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">App\Cache</span><span class="p">;</span>

<span class="nv">$func</span> <span class="o">=</span> <span class="n">test</span><span class="o">::</span><span class="nf">func</span><span class="p">(</span><span class="s1">'App\Cache'</span><span class="p">,</span> <span class="s1">'file_put_contents'</span><span class="p">);</span>
<span class="nv">$cache</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileCache</span><span class="p">;</span>
<span class="nv">$cache</span><span class="o">-&gt;</span><span class="nf">store</span><span class="p">(</span><span class="s1">'hello'</span><span class="p">);</span> <span class="c1">// calls file_put_contents</span>
<span class="nv">$func</span><span class="o">-&gt;</span><span class="nf">verifyInvoked</span><span class="p">();</span> <span class="c1">// verifies file_put_content was called</span>
<span class="n">test</span><span class="o">::</span><span class="nf">cleanup</span><span class="p">();</span> <span class="c1">// restore original function</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Same can be done for time functions:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">demo</span><span class="p">;</span>
<span class="n">test</span><span class="o">::</span><span class="nf">func</span><span class="p">(</span><span class="s1">'demo'</span><span class="p">,</span> <span class="s1">'time'</span><span class="p">,</span> <span class="s1">'now'</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="s1">'now'</span><span class="p">,</span> <span class="nb">time</span><span class="p">());</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>You can install latest AspectMock via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="s2">"codeception/aspect-mock:~0.5"</span></code></pre></figure>

<h2 id="codeception-21">Codeception 2.1</h2>

<p>Next major release of Codeception will include new features, breaking changes, with ability to keep backwards compatibility. Here are the most interesting features you should wait for:</p>

<ul>
  <li>All support classes like actors, steps, pages, etc, will be moved to <code class="language-plaintext highlighter-rouge">tests/_support</code> directory.</li>
  <li>Support classes <a href="https://github.com/Codeception/Codeception/pull/1228">will use PSR-4 standard</a>.</li>
  <li>Dependency Injection. All support and test classes can be included one into another: Pages can be injected into Helpers, Helpers can be injected into Cest classes, etc.</li>
  <li>Module Conflicts. Lots of issues are happening when users try ot include modules with same apis into one suite. Like <code class="language-plaintext highlighter-rouge">PhpBrowser</code> + <code class="language-plaintext highlighter-rouge">Laravel4</code> + <code class="language-plaintext highlighter-rouge">WebDriver</code>. Those module is possible to be used together, but possibly that was not really intended to be used this way. Call to <code class="language-plaintext highlighter-rouge">$I-&gt;amOnPage</code> may be executed by any provided modules depending on the order of their declaration. This leads to unpredictable errors, and is the source of confusion. In 2.1 Codeception will allow to define module conflicts, and throw exceptions if modules are not expected to be used together.</li>
  <li><a href="https://github.com/Codeception/Codeception/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.1">…and more</a></li>
</ul>

<h2 id="global-installation">Global Installation</h2>

<p>One of recently discussed topics for Codeception, was <a href="https://github.com/Codeception/Codeception/issues/1238">global installation of Codeception</a>. From now on you can install Codeception globally using Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer global require <span class="s1">'codeception/codeception=2.0.*'</span></code></pre></figure>

<p>This will be recommended installation method since Codeception 2.1.</p>

<h2 id="roboci">RoboCI</h2>

<p>This project that desires its own post in this blog. It is open-source reproduction of Travis CI using <a href="https://docker.io">Docker</a> and Travis Cookbooks. <a href="https://github.com/Codegyre/RoboCI">RoboCI</a> can be use to execute Travis CI tests locally or on remote server. It does not require VirtualBox nor Vagrant installed. It was executed with Codeception internal tests, with Selenium + Firefox, MySQL, PostgreSQL, MongoDb, and other services. <a href="https://phptest.club/t/roboci-run-travisci-builds-locally/170">You can read more about RoboCI</a> and try it in your projects. In future we plan to provide consulting services on using RoboCI with Codeception or any other PHP testing framework. Stay in touch for updates!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Unit Testing With Database</title>
      <link>https://codeception.com/06-28-2014/unit-testing-with-database.html</link>
      <pubDate>Sat, 28 Jun 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-28-2014/unit-testing-with-database</guid>
      <description><![CDATA[ <p>He-hey! You just opened this page to say that there is no such thing as unit testing with database. Unit tests are supposed to test isolated pieces, and sure unit tests should not touch the database. And we can agree with that. But it happened that “unit test” term is far more popular then “integration test”. Unit test have one very strong requirement. Isolation. Complete isolation from other code units and services. In real world we can spoil our lives trying to achieve complete isolation. And even when with pain and sweat we finally got out models isolated from database, we receive a very strange class of tests. They do not provide a valuable feedback. Model test that does not connect to real database is useless, as it provide false positive results, and the code behind may crash connecting to real storage. So what do we want from unit test after all? To be written in complete isolation (what for?), or provide real feedback?</p>

<p>So let’s not to concentrate on terms. Let’s concentrate on testing.</p>

<h2 id="testing-faster-with-transactions">Testing Faster With Transactions</h2>

<p>What drawbacks we receive if unit tests are connecting to database? Sure it will be dramatic slowdown. We will need to connect to database, insert data, and perform a cleanup afterwards. The most simple way of cleaning things up is to repopulate database completely. Yet, this is the slowest way. But there is a much better way of doing things. Especially for unit (and functional) tests. We can use <strong>transactions</strong>.</p>

<p>That’s right. We can cover a test into transaction, and rollback it after the test is finished. This is the fastest and the most stable way of working with database in unit tests. The only issue with it is that not all databases support nested transactions. For instance, in MySQL you can’t begin transaction and begin next transaction as there can be only one at one point. Yet, those nested transactions can be emulated. And here are good news: if you use one of popular PHP Frameworks: <strong>Laravel</strong>, <strong>Yii2</strong>, <strong>Phalcon</strong>, or <strong>Doctrine ORM</strong>, your framework already can do that! Thus, in unit test you can begin transaction in setup, and finish it in teardown of a test. Sure, you should use the framework’s database layer for that.</p>

<p>In Codeception we already use this feature for speeding up functional tests. But it was not that obvious that you can use the same practice for unit tests.</p>

<p>Let’s connect our framework to the <code class="language-plaintext highlighter-rouge">unit.suite.yml</code>. In current example we will use Laravel, yet very similar steps can be done for Yii2, Phalcon, and Symfony+Doctrine.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="c1"># Codeception Test Suite Configuration</span>

<span class="c1"># suite for unit (internal) tests.</span>
<span class="na">class_name</span><span class="pi">:</span> <span class="s">UnitTester</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Laravel4</span><span class="pi">,</span> <span class="nv">UnitHelper</span><span class="pi">,</span> <span class="nv">Asserts</span><span class="pi">]</span></code></pre></figure>

<p>That’s all. <a href="https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Module/Laravel4.php#L104">This line</a> of Laravel module will start the transaction before each test in suite.</p>

<h2 id="using-activerecord-helpers">Using ActiveRecord Helpers</h2>

<p>Laravel, Phalcon, and Yii are frameworks that use ActiveRecord pattern for working with database. Codeception Framework modules have built-in helpers, which share the <a href="https://github.com/Codeception/Codeception/blob/2.0/src/Codeception/Lib/Interfaces/ActiveRecord.php">standard interface</a> to work with database records.</p>

<p>Let’s write a sample Laravel test which demonstrates usage of Codeception helpers. In this example we will test <code class="language-plaintext highlighter-rouge">activate</code> method of User model. It activates user when provided activation key matches predefined one.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">UserTest</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\TestCase\Test</span>
<span class="p">{</span>
    <span class="cd">/**
     * @var UnitTester
     */</span>
    <span class="k">protected</span> <span class="nv">$tester</span><span class="p">;</span>

    <span class="k">protected</span> <span class="nv">$user_id</span><span class="p">;</span>

    <span class="k">function</span> <span class="n">_before</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">// preparing a user, inserting user record to database</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user_id</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">haveRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="p">[</span>
            <span class="s1">'username'</span> <span class="o">=&gt;</span> <span class="s1">'John'</span><span class="p">,</span>
            <span class="s1">'email'</span> <span class="o">=&gt;</span> <span class="s1">'john@snow.com'</span><span class="p">,</span>
            <span class="s1">'activation_key'</span> <span class="o">=&gt;</span> <span class="s1">'123456'</span><span class="p">,</span>
            <span class="s1">'is_active'</span> <span class="o">=&gt;</span> <span class="mi">0</span>

        <span class="p">]);</span>
    <span class="p">}</span>

    <span class="k">function</span> <span class="n">testUserCanBeActivatedWithValidKey</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">// lookup for user with Eloquent API</span>
        <span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">find</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user_id</span><span class="p">);</span>
        <span class="c1">// executing action</span>
        <span class="nv">$isActivated</span> <span class="o">=</span> <span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">activate</span><span class="p">(</span><span class="s1">'123456'</span><span class="p">));</span>
        <span class="c1">// performing assertion</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$isActivated</span><span class="p">);</span>
        <span class="c1">// checking that data was actually saved into database</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">seeRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="p">[</span>
            <span class="s1">'id'</span> <span class="o">=&gt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user_id</span><span class="p">,</span>
            <span class="s1">'is_active'</span> <span class="o">=&gt;</span> <span class="mi">1</span>
         <span class="p">]);</span>
    <span class="p">}</span>

    <span class="k">function</span> <span class="n">testUserNotActivatedWithInvalidKey</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">find</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user_id</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">activate</span><span class="p">(</span><span class="s1">'00000'</span><span class="p">));</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">dontSeeRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="p">[</span>
            <span class="s1">'id'</span> <span class="o">=&gt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user_id</span><span class="p">,</span>
            <span class="s1">'is_active'</span> <span class="o">=&gt;</span> <span class="mi">1</span>
         <span class="p">]);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As it was mentioned, similar test can be written for other mentioned frameworks. Depending on framework API ActiveRecord helper methods</p>

<ul>
  <li>grabRecord</li>
  <li>seeRecord</li>
  <li>haveRecord</li>
  <li>doneSeeRecord</li>
</ul>

<p>may take table name (Laravel) or model name (Phalcon, Yii2).</p>

<h2 id="who-is-that-tester">Who is that Tester?</h2>

<p><code class="language-plaintext highlighter-rouge">$this-&gt;tester</code> object used here is instance of <a href="https://codeception.com/docs/02-GettingStarted#Actors">Actor class</a> and contain all methods of  modules and helpers used in unit suite. It would be a good idea to put any shared code into helpers, and reuse across test cases by accessing <code class="language-plaintext highlighter-rouge">$this-&gt;tester</code>. This object is injected into any testcase that extends <code class="language-plaintext highlighter-rouge">Codeception\TestCase\Test</code>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Sure, we could implement similar test using just Eloquent API without using Codeception helpers. Still, they are quite useful. Especially assertion methods like <code class="language-plaintext highlighter-rouge">seeRecord</code> which queries database for a record with given attributes.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0.1 and Changelog page</title>
      <link>https://codeception.com/06-21-2014/codeception-2.0.1-and-changelog-page.html</link>
      <pubDate>Sat, 21 Jun 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-21-2014/codeception-2.0.1-and-changelog-page</guid>
      <description><![CDATA[ <p>First bugfix release from the 2.0 version. This release introduces very important fix for running Codeception with PHP 5.4.x. Due to bug in PHP you would see strange errors while <a href="https://github.com/Codeception/Codeception/issues/1084">trying to execute Cept files</a>. We can’t say which exect PHP 5.4 versions were affected, but if you had issues running Codeception 2.0 earlier, please upgrade.</p>

<p>The next notable change is <code class="language-plaintext highlighter-rouge">see</code> method of WebDriver module. Now it checks for a visible text on a page. If you need to check if text is present inside HTML source of a page you can use newly added <code class="language-plaintext highlighter-rouge">seeInPageSource</code> method for that. Thanks <strong>artyfarty</strong> for this bugfix.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar self-update</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update codeception/codeception</code></pre></figure>

<h1 id="changelog-page">Changelog Page</h1>

<p>From now on there will be no blogposts for minor releases. There is new <a href="/changelog">changelog</a> page which displays changes in latest releases. You should refer to it in order to follow the updates. Important changes, features, bugfixes will be mentioned there.</p>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0 Final</title>
      <link>https://codeception.com/06-06-2014/codeception-2.0-final.html</link>
      <pubDate>Fri, 06 Jun 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-06-2014/codeception-2.0-final</guid>
      <description><![CDATA[ <p>Codeception 2.0 is out. It was a long journey to get here but it was worth it.
Main purpose of making Codeception 2.0 was not to break things up. Instead we focused on making Codeception simpler in use and reduce that awkward WTF moments you were experiencing rebuilding Guy classes and discovering dark magic of <code class="language-plaintext highlighter-rouge">Maybe</code> object.</p>

<p>That’s it. Codeception does not have 2-phases of execution and runs your tests as native PHP scenarios. It also does not require you to rebuild actor classes on configuration change - it is done automatically. And at last we don’t have Guys anymore. They were renamed in more neutral <code class="language-plaintext highlighter-rouge">Tester</code> objects. But it is up to you how will you call your actors: Testers, Guys, or even ninjas, those names can be configured!</p>

<h3 id="naming-conventions">Naming Conventions</h3>

<p>We decided to change some naming conventions in Codeception.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">_log</code> directory was renamed to <code class="language-plaintext highlighter-rouge">_output</code>. It was logical decision, as Codeception does not print any logs by default, but constantly uses <code class="language-plaintext highlighter-rouge">_log</code> directory for printing debug information and reports.</li>
  <li><code class="language-plaintext highlighter-rouge">_helpers</code> was renamed to <code class="language-plaintext highlighter-rouge">_support</code>. Now it is more obvious that this directory may contain not only helpers but any kind of support code required for tests.</li>
</ul>

<p>As it was said, Guys were renamed to Testers. Actor classes and helpers are named by suite. For instance, acceptance test will start with this line:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AcceptanceTester</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="c1">// and uses AcceptanceHelper</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In unit tests we simplified access to actor classes by just using <code class="language-plaintext highlighter-rouge">$this-&gt;tester</code> property (actor title). Looks a bit more readable.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">function</span> <span class="n">testSavingUser</span><span class="p">()</span>
<span class="p">{</span>
    <span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">User</span><span class="p">();</span>
    <span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="s1">'Miles Davis'</span><span class="p">);</span>
    <span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">save</span><span class="p">();</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">tester</span><span class="o">-&gt;</span><span class="nf">seeInDatabase</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span><span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Miles'</span><span class="p">,</span> <span class="s1">'surname'</span> <span class="o">=&gt;</span> <span class="s1">'Davis'</span><span class="p">));</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>If you are upgrading from 1.x you can still use <code class="language-plaintext highlighter-rouge">codeGuy</code> as it was left for compatibility.</p>

<p><strong>Listed naming changes are recommended defaults. You don’t need to follow them if you plan to upgrade from 1.x</strong>.</p>

<h3 id="changes">Changes</h3>

<p>Let’s briefly name some important changes added in Codeception 2.0</p>

<ul>
  <li>PHP &gt;= 5.4</li>
  <li>Upgraded to PHPUnit 4.x</li>
  <li>Upgraded to Guzzle 4.x</li>
  <li>Removed Mink (and Selenium, Selenium2, ZombieJS modules)</li>
  <li>Removed Goutte</li>
  <li>Logger moved to extension and disabled by default</li>
  <li>Naming conventions changed</li>
  <li>One-time execution for all tests</li>
  <li>Autorebuild of actor classes</li>
  <li>MultiSession testing with Friends</li>
  <li>Strict Locators introduced</li>
  <li>Fail fast option <code class="language-plaintext highlighter-rouge">-f</code> added to <code class="language-plaintext highlighter-rouge">run</code> command</li>
  <li>Coverage options changed behavior in <code class="language-plaintext highlighter-rouge">run</code> command</li>
  <li>Bootstrap test are loaded suite, not before each test</li>
  <li>Parallel Execution (!!!)</li>
</ul>

<h3 id="guides">Guides</h3>

<p>Guides were reviewed and updated for 2.0 release. <a href="https://codeception.com/docs/06-UnitTests">Unit Testing</a> guide was completely rewritten, and new chapter <a href="https://codeception.com/docs/12-ParallelExecution">Parallel Execution</a> was added. Please note that parallel running tests is advanced feature and will require some time for you for set everything up correctly. But If your tests run longer then 30 minutes, you will get a real benefit out of it.</p>

<h3 id="the-most-important-bug-fixed">The Most Important Bug Fixed</h3>

<p>The Most Important Bug was reported by many of our users:</p>

<blockquote class="twitter-tweet" lang="uk"><p><a href="https://twitter.com/codeception">@codeception</a> Nice website footer: © 2011 - &lt;?php date(&#39;Y&#39;) ?&gt;&#10;You should create a test for that ;-)</p>&mdash; Bret R. Zaun (@bretrzaun) <a href="https://twitter.com/bretrzaun/statuses/401300578246352896">November 15, 2013</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="uk"><p>Hey, <a href="https://twitter.com/codeception">@codeception</a> you have unparsed PHP in your footer.</p>&mdash; Phil Kershaw (@PhilKershaw) <a href="https://twitter.com/PhilKershaw/statuses/454226393401135104">April 10, 2014</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="uk"><p>Oh <a href="https://twitter.com/codeception">@codeception</a> !!!!!! Should _really_ fix this. lol. &lt;3&lt;3&lt;3 <a href="https://t.co/Wi3szPMKMN">pic.twitter.com/Wi3szPMKMN</a></p>&mdash; Darren Nolan (@DarrenNolan_) <a href="https://twitter.com/DarrenNolan_/statuses/469972297613185026">May 23, 2014</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>We decided to fix it for 2.0 release. Now the date in footer is displayed <strong>correctly</strong> according to PHP rules (using <code class="language-plaintext highlighter-rouge">&lt;?=</code>).</p>

<h3 id="upgrading">Upgrading</h3>

<p>Codeception 2.0 was publishing pre-releases since February. Lots of developers already gave it a try and reported their issues. We hope the upgrade will go smoothly for you. Basically what you need is to:</p>

<ul>
  <li>run <code class="language-plaintext highlighter-rouge">build</code> command</li>
  <li>remove any internal usage of Mink or Goutte</li>
  <li>remove any usage of <code class="language-plaintext highlighter-rouge">$scenario-&gt;prepare()</code> as it always return false now</li>
  <li><em>optionally</em> remove <code class="language-plaintext highlighter-rouge">$scenario-&gt;running()</code> calls and <code class="language-plaintext highlighter-rouge">$I-&gt;execute</code> calls. They are not required anymore.</li>
  <li>take a look into PhpBrowser module which is uses Guzzle4 directly. You may have issues with using it (as it was completely rewritten). Please report those issues to GitHub.</li>
  <li>Selenium2 module should be replaced with WebDriver (as you already didn’t do so).</li>
  <li>if you use variables in <code class="language-plaintext highlighter-rouge">_bootstrap.php</code>, rename it to <code class="language-plaintext highlighter-rouge">_fixtures.php</code> and load it manually into your tests.</li>
</ul>

<p>If you have issues during upgrade send issues to GitHub and we will make upgrade more smoother.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar</code></pre></figure>

<p>Via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:2.0.0"</span> </code></pre></figure>

<p>P.S. Codeception 1.8.6 was released as well. List of its changes will go tomorrow.</p>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0 RC2: Guzzle 4</title>
      <link>https://codeception.com/05-13-2014/codeception-2rc2-guzzle-4.html</link>
      <pubDate>Tue, 13 May 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-13-2014/codeception-2rc2--guzzle-4</guid>
      <description><![CDATA[ <p>Unfortunately this is not a final release of Codeception 2.0 you may have expected. Still we had to get another release candidate in order to implement one breaking and important change: upgrade to Guzzle version 4.</p>

<p>As you know PHPBroswer of Codeception used Mink, Goutte, and Guzzle to emulate visiting pages, filling forms, and other user-like web interaction. Recently Guzzle got a new major release, so we had to upgrade Codeception as well. We also removed Mink and Goutte and Codeception uses Guzzle directly. This will allow us faster to hunt down and fix the issues which may appear in future.</p>

<p>Guzzle changed their package name and namespace in latest release. If you were using Guzzle 3 and you want to upgrade to Codeception 2 you won’t get any conflicts in dependencies. But if you were using <code class="language-plaintext highlighter-rouge">Guzzle\Http\Client</code> class in your tests or helpers you will to change it to <code class="language-plaintext highlighter-rouge">GuzzleHttp\Client</code>.</p>

<h2 id="phpbrowser-additional-configuration">PHPBrowser additional configuration</h2>

<p>Guzzle4 got very flexible configuration. You may omit <code class="language-plaintext highlighter-rouge">CURL_</code> constants and use <a href="https://docs.guzzlephp.org/en/latest/clients.html#request-options">request parameters</a> to set headers, auth, cookies, and SSL verification. Codeception now accepts all request parameters of Guzzle in module configuration part:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"> 
<span class="na">modules</span><span class="pi">:</span>
   <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">PhpBrowser</span><span class="pi">]</span>
   <span class="na">config</span><span class="pi">:</span>
      <span class="na">PhpBrowser</span><span class="pi">:</span>
         <span class="na">url</span><span class="pi">:</span> <span class="s1">'</span><span class="s">http://localhost'</span>
         <span class="na">auth</span><span class="pi">:</span> <span class="pi">[</span><span class="s1">'</span><span class="s">admin'</span><span class="pi">,</span> <span class="s1">'</span><span class="s">123345]</span>
         <span class="s">headers:</span>
            <span class="s">'</span><span class="nv">User-Agent'</span><span class="pi">:</span> <span class="s1">'</span><span class="s">Codeception'</span>
            <span class="nv">Accept</span><span class="pi">:</span> <span class="s1">'</span><span class="s">application/json'</span>
         <span class="nv">curl</span><span class="pi">:</span>
             <span class="nv">CURLOPT_RETURNTRANSFER</span><span class="pi">:</span> <span class="nv">true</span></code></pre></figure>

<p>And yes, <code class="language-plaintext highlighter-rouge">curl</code> configuration section is left for more advanced options and for backwards compatibility. BTW, SSL settings should be also defined via new configuration using <code class="language-plaintext highlighter-rouge">verify</code>, <code class="language-plaintext highlighter-rouge">cert</code>, <code class="language-plaintext highlighter-rouge">ssl_key</code> request options.</p>

<h2 id="try-it">Try it</h2>

<p>As usual we need your feedback. Guzzle upgrade is very dramatic change and we recommend to try it on your test suites. If you have issues report them and we will try to fix them before the final release, which is schenduled for next week.</p>

<p>Download:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/2.0.0-RC2/codecept.phar</code></pre></figure>

<p>Via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:2.0.0-RC2"</span> </code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0 RC: Strict Locators</title>
      <link>https://codeception.com/05-01-2014/codeception-2.0-rc-strict-locators.html</link>
      <pubDate>Thu, 01 May 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-01-2014/codeception-2.0-rc--strict-locators</guid>
      <description><![CDATA[ <p>Codeception 2.0 is almost ready for final release. Thanks for everyone who already running alpha/beta version of Codeception and provides us with valuable feedback. If everything goes well the final release will be published in a week. The delay between releases is dictated by the need to allow parallel tests execution. As it was said before: Codeception won’t provide parallel test running out of the box, yet we will add a new chapter into guides where you will learn how to implement parallelism model that matches needs of your project.</p>

<h2 id="improvements">Improvements</h2>

<h3 id="strict-locators">Strict Locators</h3>

<p>In order to provide better element locations you can now specify locators explicitly like this: <code class="language-plaintext highlighter-rouge">['css' =&gt; 'input.name']</code>. This will work for PHPBrowser, Frameworks modules, and WebDriver.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">([</span><span class="s1">'css'</span> <span class="o">=&gt;</span> <span class="s1">'input.name'</span><span class="p">],</span> <span class="s1">'jon'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">([</span><span class="s1">'link'</span> <span class="o">=&gt;</span> <span class="s1">'Submit'</span><span class="p">]);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeElement</span><span class="p">([</span><span class="s1">'xpath'</span> <span class="o">=&gt;</span> <span class="s1">'.//div[@data-name="jon"]'</span><span class="p">]);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Allowed locator mechanisms are:</p>

<ul>
  <li>id</li>
  <li>name</li>
  <li>css</li>
  <li>xpath</li>
  <li>link</li>
  <li>class</li>
</ul>

<p>You can use strict locators in your Page Object classes as well.</p>

<h3 id="see-element-with-attributes">See Element with Attributes</h3>

<p>To improve checking element with expected attributes <code class="language-plaintext highlighter-rouge">seeElement</code> now takes second parameter:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/form/field'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeElement</span><span class="p">(</span><span class="s1">'input[name=login]'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeElement</span><span class="p">(</span><span class="s1">'input'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'login'</span><span class="p">]);</span> <span class="c1">// same as above</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">dontSeeElement</code> works in corresponding manner.</p>

<h3 id="grabattributefrom-method-added">grabAttributeFrom method added</h3>

<p>To fetch value of attribute of element:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/search'</span><span class="p">);</span>
<span class="nv">$attr</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabAttributeFrom</span><span class="p">(</span><span class="s1">'form'</span><span class="p">,</span> <span class="s1">'method'</span><span class="p">);</span>
<span class="nv">$attr</span> <span class="o">==</span> <span class="s1">'GET'</span>
<span class="cp">?&gt;</span></code></pre></figure>

<hr />

<p>Also <code class="language-plaintext highlighter-rouge">makeScreenshot</code> method of WebDriver was simplified. Filename of saved screenshot does not include a test name.</p>

<h2 id="try-it">Try it</h2>

<p>Download:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/2.0.0-RC/codecept.phar</code></pre></figure>

<p>Via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:2.0.0-RC"</span> </code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8.5</title>
      <link>https://codeception.com/04-05-2014/codeception-1.8.5.html</link>
      <pubDate>Sat, 05 Apr 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/04-05-2014/codeception-1.8.5</guid>
      <description><![CDATA[ <p>New improvements and bugfixes came during the last month into the 1.8 branch. We summarized them all and prepared a new release.</p>

<h2 id="ecosystem">Ecosystem</h2>

<p>But before we proceed you should check out the new <a href="https://codeception.com/addons">Addons</a> section on this site. We had only extensions listed there, but now you can find new modules and even applications there. And let’s name at least two projects you should definitely be aware of:</p>

<ul>
  <li><a href="https://github.com/jayhealey/Webception">WebCeption</a> - web interface for Codeception.</li>
  <li><a href="https://github.com/DigitalProducts/codeception-module-visualception">VisualCeption</a> - module for visual regression tests.</li>
</ul>

<p>Thank you for all extensions and modules developers. If you developed a module, helper, or extension, share your work with others by adding your project to addons page (click <code class="language-plaintext highlighter-rouge">Edit</code> link in the bottom).</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>[WebDriver] facebook/webdriver version was set strictly to 0.3. And this won’t be changed in future for 1.8 branch. We accidentaly commited <code class="language-plaintext highlighter-rouge">~0.3</code> into the 1.8.4 which made composer to install 0.4 version of facebook/webdriver. There was API break in 0.4, so WebDriver module didn’t work properly.</li>
  <li>[Phalcon] Phalcon 1.3 compatibility added <a href="https://github.com/Codeception/Codeception/issues/944">#944</a></li>
  <li>[Laravel] Service providers are now correcly loaded by <strong>ShawnMcCool</strong>.</li>
  <li>[Laravel] <code class="language-plaintext highlighter-rouge">findRecord</code> fixed by <strong>andkom</strong>.</li>
  <li>[ZF2] Fixed handling of query parameters by <strong>piccagliani</strong>.</li>
  <li>[Frameworks] Fixed problem with submitting form with input[type=image] by <strong>piccagliani</strong>.</li>
</ul>

<h2 id="features">Features</h2>

<ul>
  <li>[Webdriver][Frameworks] input field can now be located by its name.</li>
  <li>[Webdriver][Frameworks] element can be clicked by name too.</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="185">1.8.5</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar self-update</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update codeception/codeception</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8.4 with minor fixes</title>
      <link>https://codeception.com/03-22-2014/codeception-1.8.4-with-minor-fixes.html</link>
      <pubDate>Sat, 22 Mar 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-22-2014/codeception-1.8.4-with-minor-fixes</guid>
      <description><![CDATA[ <p>Bugfix release on stable 1.8 branch. While you are waiting for 2.0 RC and final version, you can update your current Codeception to get the newest patches and updates. Here they are:</p>

<ul>
  <li>[WebDriver] Correctly return to main page when switchToIFrame() is called by ** n8whnp**.</li>
  <li>[WebDriver] fixed screenshot capture by <strong>FnTm</strong>.</li>
  <li>[Frameworks] More details in debug output by <strong>Ragazzo</strong>.</li>
  <li>Fixed problem with encoding in $I-&gt;wantTo() by <strong>vgoodvin</strong>.</li>
  <li>Add clone and unset capabilites to <code class="language-plaintext highlighter-rouge">Maybe</code> by <strong>brutuscat</strong>.</li>
  <li>[WebDriver] Fixes to submitForm when typing password by <strong>pcairns</strong>.</li>
  <li>[Phalcon1] haveRecord return id even when id is not public by <strong>xavier-rodet</strong>.</li>
  <li>Modules to be loaded from global context by <strong>Ragazzo</strong>. Now you can pass long name of module into module configuration:</li>
</ul>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">WebGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">\My\Custom\Module</span><span class="pi">,</span> <span class="nv">WebHelper</span><span class="pi">]</span></code></pre></figure>

<p>Really helpful feature if you have multiple Codeception inits in one project and you want to have shared module.</p>

<p>All those features were included in 2.0-beta. Thanks to all contributors!</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="184">1.8.4</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar self-update</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update codeception/codeception</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0 beta</title>
      <link>https://codeception.com/03-18-2014/codeception-2.0-beta.html</link>
      <pubDate>Tue, 18 Mar 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-18-2014/codeception-2.0-beta</guid>
      <description><![CDATA[ <p>It took about a month to get to the beta release. This release brings lots of changes even a few BC breaks and clearly shows what Codeception 2.0 is planning to be. Today we will announce more technical changes, and not conceptual ones. As it was stated previously: Codeception 2.0 will bring lots of small improvements, will be much easier to extend, and understand. Changes for beta release were not planned initially, but were added to help Codeception evolve during the 2.0 branch development. Let’s list briefly all major changes and see how to deal with them. <a href="https://github.com/Codeception/Codeception/tree/master/docs">Documentation for 2.0 branch</a> can be found on GitHub and will be published on RC release.</p>

<h2 id="changes">Changes</h2>

<ul>
  <li>Upgraded to PHPUnit 4.0</li>
  <li>Upgraded to facebook/webdriver 0.4</li>
  <li><strong>RunFailed</strong> extension added. To rerun tests on fail include <code class="language-plaintext highlighter-rouge">Codeception\Platform\RunFailed</code> extension, and call <code class="language-plaintext highlighter-rouge">codecept run -g failed</code>.</li>
  <li><strong>Logger disabled</strong> by default and moved to Extension. You will need to install Monolog by yourself, and enable <code class="language-plaintext highlighter-rouge">Codeception\Platform\Logger</code> as extension.</li>
  <li>Methods <code class="language-plaintext highlighter-rouge">_before</code>/<code class="language-plaintext highlighter-rouge">_after</code> of Cest can use <code class="language-plaintext highlighter-rouge">$I</code> object.</li>
  <li>Destination for xml/html/reports can be customized. For instance</li>
</ul>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">codecept run <span class="nt">--xml</span> myreport.xml
codecept run <span class="nt">--xml</span> /home/davert/report.xml
codecept run <span class="nt">-g</span> database <span class="nt">--xml</span> database.xml
<span class="sb">```</span></code></pre></figure>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--coverage</code> + <code class="language-plaintext highlighter-rouge">--xml</code> or <code class="language-plaintext highlighter-rouge">--html</code> won’t produce xml or html codecoverage output. Use new options <code class="language-plaintext highlighter-rouge">coverage-xml</code> and <code class="language-plaintext highlighter-rouge">coverage-html</code> instead. They were added so you could specify custom destination for codecoverage reports as well.</li>
  <li>you can get current environment in a test by accessing <code class="language-plaintext highlighter-rouge">$this-&gt;env</code> (even in Cept)</li>
  <li>shortcut functions added: <code class="language-plaintext highlighter-rouge">codecept_debug</code> to print custom output in debug mode, <code class="language-plaintext highlighter-rouge">codecept_root_dir</code>, <code class="language-plaintext highlighter-rouge">codecept_log_dir</code>, <code class="language-plaintext highlighter-rouge">codecept_data_dir</code> for retrieving Codeception paths.</li>
  <li>extensions can change global config before processing.</li>
</ul>

<h2 id="breaking-changes">Breaking Changes</h2>

<p>In Codeception 1.x bootstrap files were used differently for different types of tests. They were introduced to pass variables (and fixtures) into Cept scenarios. They were almost useless in Cests, and absolutely useless for Test files. They are not removed at all, but now they are loaded only once before the suite. If you were using bootstrap files for setting fixtures, you still can use them, but you will need to require them manually.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">require</span> <span class="k">__DIR__</span> <span class="mf">.</span> <span class="s1">'/_bootstrap.php'</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The same way you can load bootstrap files into Cests. But we recommend to create <code class="language-plaintext highlighter-rouge">_fixtures.php</code> file, and use bootstrap file for suite initialization.</p>

<h2 id="dynamic-groups">Dynamic Groups</h2>

<p>One significant internal feature is dynamic groups. You can save test names into file and run them inside a group. That’s how the <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Platform/RunFailed.php">RunFailed</a> extension works: it saves names of failed tests into file <code class="language-plaintext highlighter-rouge">tests/_log/failed</code>, then execute <code class="language-plaintext highlighter-rouge">codecept run -g failed</code> to run these tests.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">groups</span><span class="pi">:</span>
  <span class="c1"># add 2 tests to db group</span>
  <span class="na">db</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">tests/unit/PersistTest.php</span><span class="pi">,</span> <span class="nv">tests/unit/DataTest.php</span><span class="pi">]</span>

  <span class="c1"># add list of tests to slow group</span>
  <span class="na">slow</span><span class="pi">:</span> <span class="s">tests/_log/slow</span></code></pre></figure>

<p>For example, you can create the list of the most slow tests, and run them inside their own group. Pretty interesting and powerful feature that also can be used to run tests in parallel.</p>

<h2 id="parallel-test-execution">Parallel Test Execution</h2>

<p>Not yet! Codeception does not support parallel test execution, nor will be provide it out of the box. That’s because there is no solution that will fit for everyone. You may want to run parallel tests locally in threads via pthreads extension, or run them on different hosts via SSH, AMQP, etc. But we already have everything to implement parallel testing.</p>

<p>Here is the algorithm:</p>

<ul>
  <li>split all tests into groups (with dynamic groups)</li>
  <li>run each groups separately</li>
  <li>merge results</li>
</ul>

<p>And we will write guides on implementing this algorithm, as well as we plan to release a sample tool that will run tests in parallel.</p>

<h2 id="try-it">Try it</h2>

<p>As usual, we need your feedback to get 2.0 released as stable.</p>

<p>Download:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/2.0.0-beta/codecept.phar</code></pre></figure>

<p>Via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:2.0.0-beta"</span> </code></pre></figure>

<p><strong>P.S.</strong> Our sponsors <a href="https://2amigos.us/"><strong>2Amigos</strong> updated their site and logo</a>. Check it out!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 2.0 alpha</title>
      <link>https://codeception.com/02-18-2014/codeception-2.0-alpha.html</link>
      <pubDate>Tue, 18 Feb 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-18-2014/codeception-2.0-alpha</guid>
      <description><![CDATA[ <p>Finally we are ready to show you Codeception 2.0. We tried not to break everything (as it was supposed for major version change), but keep things work as they are, but maybe in a different way. Let’s review the most important changes:</p>

<h2 id="codeception-not-just-for-guys">Codeception: Not Just For Guys</h2>

<p>Before 2.0 there were only Guys in it. That is not fair! We wanted to make Codeception a tool for everyone: for guys, girls, developers, test engineers, ninjas and even wookiees… <em>(nope, wookiees should wait for 3.0)</em>.</p>

<p>That’s why you can now choose the desired actor from a list during the <code class="language-plaintext highlighter-rouge">bootstrap</code> process.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Before proceed you can choose default actor:

$I = new [ACTOR]
  Select an actor. Default: Guy  
  [0] Guy
  [1] Girl
  [2] Person
  [3] Engineer
  [4] Ninja
  [5] Dev

</code></pre></div></div>

<p>so you all your test actors (that’s how we call guy classes now) will be in form like <code class="language-plaintext highlighter-rouge">TestGirl</code>, <code class="language-plaintext highlighter-rouge">WebNinja</code>, <code class="language-plaintext highlighter-rouge">CodeDev</code>, etc. Pretty flexible.</p>

<h2 id="codeception-not-alone">Codeception: Not Alone</h2>

<p>Before Codeception 2.0 guys (or should we say actors now) were left to themselves. You know, it is so sad to see that there is only <code class="language-plaintext highlighter-rouge">$I</code> in the test, forever alone, like on a desert island, or in space… But in 2.0 you can invite some friends into your tests. Let’s say…</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$nick</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveFriend</span><span class="p">(</span><span class="s1">'nick'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>So we can write <strong>multi-session tests</strong> that can be executed in two browser windows. 
You may try to run this test on <code class="language-plaintext highlighter-rouge">github.com</code> to see how it works:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'surf Github with Nick'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">submitForm</span><span class="p">(</span><span class="s1">'#top_search_form'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'q'</span> <span class="o">=&gt;</span> <span class="s1">'php-webdriver'</span><span class="p">));</span>
<span class="nv">$nick</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveFriend</span><span class="p">(</span><span class="s1">'nick'</span><span class="p">);</span>
<span class="nv">$nick</span><span class="o">-&gt;</span><span class="nf">does</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="kt">WebGuy</span> <span class="nv">$I</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/Codeception/Codeception'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Issues'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">canSeeInTitle</span><span class="p">(</span><span class="s1">'Issues'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'li.public:nth-child(1) &gt; h3:nth-child(3) &gt; a:nth-child(1) &gt; em:nth-child(2)'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInTitle</span><span class="p">(</span><span class="s2">"php-webdriver"</span><span class="p">);</span>
<span class="nv">$nick</span><span class="o">-&gt;</span><span class="nf">does</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="kt">WebGuy</span> <span class="nv">$I</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Milestones'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">canSeeInTitle</span><span class="p">(</span><span class="s1">'Milestones'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeCurrentUrlEquals</span><span class="p">(</span><span class="s1">'/facebook/php-webdriver'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Issues'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">canSeeInTitle</span><span class="p">(</span><span class="s1">'Issues'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see, everything in <code class="language-plaintext highlighter-rouge">does</code> closure is executed in separate session. This way you can test user-to-user interactions on your site. For example Alice writes a private message to Bob and Bob responds back. Similarly you can have multiple REST sessions in a test.</p>

<p>Such scenario cases can be implemented. That’s what friends are for.</p>

<h2 id="notable-changes">Notable Changes</h2>

<p>As it was announced earlier, the main goals for Codeception 2.0 was internal refactoring.</p>

<ul>
  <li><strong>Mink (and its drivers) was removed completely</strong>. Instead you can use WebDriver module to do Selenium testing, and PhpBrowser (which uses Goutte) for browser-emulation. PhpBrowser module is now more compatible with frameworks modules, they use the same methods and acts in the same manner. If you were using <code class="language-plaintext highlighter-rouge">Selenium</code> or <code class="language-plaintext highlighter-rouge">Selenium2</code> module you should switch to <strong>WebDriver</strong>, for PHPBrowser everything should <em>(crossing fingers)</em> work smoothly.</li>
  <li><strong>2-phases test execution with tricky magic including usage of <code class="language-plaintext highlighter-rouge">Maybe</code> class was removed</strong>. Tests are now executed one time, like any regular PHP file. So you can use any PHP code in your tests, and appearance of Maybe object would not confuse you anymore.</li>
</ul>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$card</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabTextFrom</span><span class="p">(</span><span class="s1">'#credit_card'</span><span class="p">)</span>
<span class="nb">var_dump</span><span class="p">(</span><span class="nv">$card</span><span class="p">);</span> <span class="c1">// was showing `Maybe` instead of real value</span>
<span class="cp">?&gt;</span></code></pre></figure>

<ul>
  <li>Codeception 2.0 require PHP 5.4 and higher. Time changes, PHP 5.3 is getting harder and harder to support, thus we decided to move to 5.4 and keep our code base up to date. And yes, we wanted to use short array syntax. We are tired to keeping write all those nasty <code class="language-plaintext highlighter-rouge">array()</code> stuff.</li>
  <li>Actor classes (initial <strong>Guy classes) are now rebuilt automatically</strong>. Thus, you want get exception when change suite configuration, or add methods to helper. Rebuilds are not required anymore.</li>
  <li>Added <strong>Assert</strong> module that can be used to write common asserts in your tests. You can now use <code class="language-plaintext highlighter-rouge">seeEquals</code>, <code class="language-plaintext highlighter-rouge">seeContains</code> and other actions inside your Cepts or Cests.</li>
  <li>Experimental: added <strong>Silex</strong> module. We need your Feedback on using it.</li>
</ul>

<h2 id="minor-internal-changes">Minor Internal Changes</h2>

<p>Refactoring, Refactoring, Refactoring. We use PSR-2 now. We rewrote CodeCoverage. We have better directory structure… More new files. What else? Oh, lets admit it, these are not the changes you would actually notice. But internals are now more clean and easy to understand <em>(Except the parts which heavily rely on PHPUnit)</em>.</p>

<h2 id="upgrading">Upgrading</h2>

<p>We’d like to ask you to try Codeception 2.0 on your projects. Before the release is ready we need to collect feedback and fix all encountered issues. You know where <a href="https://github.com/Codeception/Codeception/issues?state=open">GitHub issues</a> are.</p>

<p>Download:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/2.0.0-alpha/codecept.phar</code></pre></figure>

<p>Via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">composer require <span class="nt">--dev</span> <span class="s2">"codeception/codeception:2.0.0-alpha"</span> </code></pre></figure>

<p>Development of 2.0 now happens in <code class="language-plaintext highlighter-rouge">master</code> branch, so keep track on changes and send your pull requests.</p>

<h2 id="some-upgrading-notes">Some Upgrading Notes</h2>

<ul>
  <li>Run <code class="language-plaintext highlighter-rouge">build</code> command</li>
  <li>Replace Selenium2 to WebDriver module</li>
  <li>Check you don’t use <code class="language-plaintext highlighter-rouge">PHPBrowser-&gt;session</code> property anywhere (it was Mink part)</li>
  <li>CodeCoverage with c3 will require <a href="https://github.com/Codeception/c3/tree/2.0">new version of c3</a>.</li>
</ul>

<h2 id="whats-next">What’s next?</h2>
<p>We need your feedback, and meanwhile we will work on updating documentation parts. 1.8.x will be maintained, but new features will be added to 2.x branch.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8.3: Laravel and Yii2 DB actions</title>
      <link>https://codeception.com/02-13-2014/codeception-1.8.3-laravel-and-yii2-db-actions.html</link>
      <pubDate>Thu, 13 Feb 2014 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-13-2014/codeception-1.8.3--laravel-and-yii2-db-actions</guid>
      <description><![CDATA[ <p>Here goes another minor release with some fixes and improvements. Codeception 1.8 now supports <strong>Laravel 4.1</strong> and <strong>Yii2</strong> and is tested for this frameworks on Travis. Also Laravel and Yii modules got some nice new actions for database interactions.</p>

<p>Laravel, Yii2, and Phalcon frameworks implement ActiveRecord pattern. That’s why all database actions in this modules look and work in a very similar manner.</p>

<h3 id="laravel-41">Laravel 4.1</h3>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$user_id</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Davert'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">dontSeeRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabRecord</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This methods will work for Laravel 4 as well, but Laravel 4.1 supports <strong>nested transactions</strong> and allows us to wrap functional test into one database transaction. This is really useful, as we can rollback any database changes we do in functional tests. Tests also run really fast, as nothing is written in database. A new <code class="language-plaintext highlighter-rouge">cleanup</code> config option was introduced to Laravel4 module, and by default it is turned on.</p>

<p>Now it is really simple to use database in your functional tests. Don’t hesitate and try <code class="language-plaintext highlighter-rouge">*Record</code> methods in action!</p>

<p>Also nice <code class="language-plaintext highlighter-rouge">seeSessionErrorMessage</code> was added by <strong>elijan</strong> to perform validation error assertions.</p>

<h3 id="yii2">Yii2</h3>

<p>Yii2 is in very active development, and its official <a href="https://github.com/yiisoft/yii2-app-basic">basic application</a> is tested with Codeception, and uses Specify and Verify libraries. Yii2 module is tested on Travis as in official Yii2 repo and in Codeception repo as well.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$user_id</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveRecord</span><span class="p">(</span><span class="s1">'app\model\users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Davert'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeRecord</span><span class="p">(</span><span class="s1">'app\model\users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">dontSeeRecord</span><span class="p">(</span><span class="s1">'app\model\users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabRecord</span><span class="p">(</span><span class="s1">'app\model\users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>ActiveRecord methods work in very similar manner. We expect that Yii2 will have nested transactions support before the release.</p>

<p>Thanks to <strong>Ragazzo</strong> for Yii2 module contributions and bughunting.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>CodeCoverage was improved. Remote codecoverage with WebDriver or PhpBrowser opens page, sends authorization cookie before the test.</li>
  <li>WebDriver cookies (and sessions) are destroyed after the test. If you have troubles when session is not restared in WebDriver - toggle <code class="language-plaintext highlighter-rouge">restart</code> option.</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="183">1.8.3</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar self-update</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update codeception/codeception</code></pre></figure>

<p>P.S. Yeah, yeah, Codeception 2.0 is on its way.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8.2: Bugfixes</title>
      <link>https://codeception.com/01-30-2014/codeception-1-8-2.html</link>
      <pubDate>Thu, 30 Jan 2014 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-30-2014/codeception-1-8-2</guid>
      <description><![CDATA[ <p>Time passed since the previous release. Since 1.8.1 we got a nice list of significant bugfixes and we are ready to publish new stable release. No new features added, actually, but they are coming in new 2.0 branch which is actively developed in this days.</p>

<p>Changes:</p>

<ul>
  <li>[REST] match similar elements in JSON arrays fixed in <a href="https://github.com/Codeception/Codeception/pull/837">#837</a> by <strong>blacknoir</strong>.</li>
  <li><code class="language-plaintext highlighter-rouge">generate:pageobject</code> now takes -c option correctly <a href="https://github.com/Codeception/Codeception/issues/809">#809</a></li>
  <li>[REST] Fixed setting Content-Type header <a href="https://github.com/Codeception/Codeception/issues/827">#827</a></li>
  <li>[REST] Headers are uppercased according to BrowserKit standard.</li>
  <li>[Db] records inserted with <code class="language-plaintext highlighter-rouge">haveInDatabase</code> now are cleaned in <code class="language-plaintext highlighter-rouge">_after</code> event by <strong>dirk-helbert</strong> <a href="https://github.com/Codeception/Codeception/issues/761">#761</a>.</li>
  <li>[Laravel] Fixed usage of <code class="language-plaintext highlighter-rouge">Redirect::back</code> in tests</li>
  <li>Fixed collecting CodeCoverage using WebDriver/Selenium2 modules.</li>
  <li>[REST] Fixed “Call to undefined method Symfony\Component\HttpFoundation\Request::getCookies() in codeception/codeception/src/Codeception/Module/REST.php line 352” by <strong>casconed</strong> <a href="https://github.com/Codeception/Codeception/pull/814">#814</a></li>
  <li>Fixed: tests run twice if you use <code class="language-plaintext highlighter-rouge">.dist.yml</code> config by <strong>tomtomsen</strong> <a href="https://github.com/Codeception/Codeception/issues/582">#582</a></li>
  <li>Environments: Test classes was loaded only once in multi-environment mode. Fixed by <strong>ayastreb</strong> and his nice tokenizer solition <a href="https://github.com/Codeception/Codeception/pull/812">#812</a></li>
  <li>Excluding running abstract classes in <code class="language-plaintext highlighter-rouge">addCest</code> by <strong>filipgorny</strong> <a href="https://github.com/Codeception/Codeception/pull/792">#792</a></li>
  <li>[PhpBrowser] Fixed setting cookies from headers</li>
  <li>[Framework] Form data on page was not cleaned after form submit. So when sending the same form twice, cached data was submitted. This is now fixed.</li>
  <li>and others…</li>
</ul>

<p>Also we’ve got a <a href="https://github.com/Codeception/MockeryModule"><strong>Mockery</strong> module</a> for using powerful Mockery framework with Codeception. It is not included in Codeception itself but can be installed via Composer. (Thanks to <strong>Jáchym Toušek</strong>)</p>

<p>Thanks to all contributors, thanks for getting bug fixed and reported. We are trying to be better with each release.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="182">1.8.2</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar self-update</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update codeception/codeception</code></pre></figure>

<h3 id="whats-next">What’s Next</h3>

<p>We are moving to Codeception 2.0. It’s first alpha is expected on next week. Stay tuned and get ready for new features!</p>

<p>While developing Codeception 2.0 we released a lightweight task runner <a href="https://github.com/CodeGyre/Robo">Robo</a>. We needed it to run routine tasks for Codeception - building phar archives, merging releases, etc. You may use it as lightweight alternative for Phing or PHP alternative for shell scripts. It’s not very documented, it doesn’t include list of all required tasks, but it will evolve. If you have ideas on improvement, or you want to add more tasks into it - please send Pull Requests.</p>

<p>And thanks to <strong>@pfaocle</strong> for the feedback on using Robo!</p>

<blockquote class="twitter-tweet" lang="uk"><p>I&#39;ve been playing w/ <a href="https://twitter.com/davert">@davert</a>&#39;s Robo this evening, converting a rickety shell script for building <a href="https://twitter.com/search?q=%23Drupal&amp;src=hash">#Drupal</a>. Very nice. <a href="https://t.co/gGtJu0EWSC">pic.twitter.com/gGtJu0EWSC</a></p>&mdash; Paul Byrne (@pfaocle) <a href="https://twitter.com/pfaocle/statuses/428671971124342784">January 29, 2014</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

 ]]></description>
    </item>
    
    <item>
      <title>Testing Emails in PHP. Part 1: PHPUnit</title>
      <link>https://codeception.com/12-15-2013/testing-emails-in-php.html</link>
      <pubDate>Sun, 15 Dec 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/12-15-2013/testing-emails-in-php</guid>
      <description><![CDATA[ <p>So how do you check that your applications sends email correctly? It looks like dealing with emails is always a challenge. How would you verify that an email message is formatted and delivered correctly, without actually sending them to your clients? That’s the first question. And the second question is: how can we automate the testing of emails?</p>

<p>For both questions we have an answer. There are two awesome services that have been developed to help developers in dealing with email hell. They are <a href="https://mailtrap.io">Mailtrap</a> and <a href="https://mailcatcher.me/">Mailcatcher</a>. Both services run an SMTP server that does not deliver emails, but stores them locally. They both have a web interface in which you can review all the outgoing emails. The difference between these services are: mailtrap runs as a web service, and mailcatcher is a ruby gem that can be installed locally.</p>

<p><img src="https://f.cl.ly/items/3w2T1p0F3g003b2i1F2z/Screen%20shot%202011-06-23%20at%2011.39.03%20PM.png" alt="mailcatcher" /></p>

<p>It’s up to you which one to use. Definitely they will simplify your life while developing a web application. Do they have something to offer for testing? Sure! We can access all handled emails via REST API and verify our assertions.</p>

<p>In this post we will marry Mailcatcher with the PHPUnit testing framework. We’ve chosen Mailcatcher so we do not have to rely on a 3rd-party web service and have all the tests run locally. We will write methods for both PHPUnit and Codeception in order to provide different solutions and compare them.</p>

<p>Before we start we need to make sure that Mailcatcher is installed and running. When done you can access it’s web interface on port <code class="language-plaintext highlighter-rouge">1080</code> and use port <code class="language-plaintext highlighter-rouge">1025</code> for the fake SMTP server. Configure your web application to use exactly that port when running in test environment.</p>

<h2 id="testing-emails-in-phpunit">Testing emails in PHPUnit</h2>

<p>Mailcatcher has a really simple REST API that is used for email access. Here is a quote from their official site.</p>

<blockquote>
  <p>A fairly RESTful URL schema means you can download a list of messages in JSON from /messages, each message’s metadata with /messages/:id.json, and then the pertinent parts with /messages/:id.html and /messages/:id.plain for the default HTML and plain text version, /messages/:id/:cid for individual attachments by CID, or the whole message with /messages/:id.source.</p>
</blockquote>

<p>What was not mentioned was that you can also clear all emails by sending <code class="language-plaintext highlighter-rouge">DELETE</code> request to <code class="language-plaintext highlighter-rouge">/messages</code>. The most complete documentation on API is <a href="https://github.com/sj26/mailcatcher/blob/master/lib/mail_catcher/web.rb">its code</a>. Even if you don’t know Ruby, it is quite easy.</p>

<p>Thus, we will need to send <code class="language-plaintext highlighter-rouge">GET</code> and <code class="language-plaintext highlighter-rouge">DELETE</code> requests and parse the json response. To send them we will use the  <a href="https://github.com/guzzle/guzzle">Guzzle</a> framework. PHPUnit and Guzzle can be easily installed via Composer:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"require-dev"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    	</span><span class="nl">"phpunit/phpunit"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
    	</span><span class="nl">"guzzle/guzzle"</span><span class="p">:</span><span class="w"> </span><span class="s2">"~3.7"</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>Let’s create <code class="language-plaintext highlighter-rouge">EmailTestCase</code> file and place MailCatcher API calls into it.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">EmailTestCase</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="cd">/**
     * @var \Guzzle\Http\Client
     */</span>
    <span class="k">private</span> <span class="nv">$mailcatcher</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nf">Guzzle\Http\Client</span><span class="p">(</span><span class="s1">'http://127.0.0.1:1080'</span><span class="p">);</span>

        <span class="c1">// clean emails between tests</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">cleanMessages</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">// api calls</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">cleanMessages</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nb">delete</span><span class="p">(</span><span class="s1">'/messages'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">getLastMessage</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$messages</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getMessages</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$messages</span><span class="p">))</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">fail</span><span class="p">(</span><span class="s2">"No messages received"</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="c1">// messages are in descending order</span>
        <span class="k">return</span> <span class="nb">reset</span><span class="p">(</span><span class="nv">$messages</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">getMessages</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$jsonResponse</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s1">'/messages'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
        <span class="k">return</span> <span class="nb">json_decode</span><span class="p">(</span><span class="nv">$jsonResponse</span><span class="o">-&gt;</span><span class="nf">getBody</span><span class="p">());</span>
    <span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>That’s enough to fetch a list of all delivered emails. All the emails will be cleaned between tests, so each test will be executed in isolation. Let’s implement some assertion methods to check the sender, recipient, subject and body of the email.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="c1">// assertions</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailIsSent</span><span class="p">(</span><span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertNotEmpty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getMessages</span><span class="p">(),</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailSubjectContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="o">-&gt;</span><span class="n">subject</span><span class="p">,</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailSubjectEquals</span><span class="p">(</span><span class="nv">$expected</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="nv">$expected</span><span class="p">,</span> <span class="nv">$email</span><span class="o">-&gt;</span><span class="n">subject</span><span class="p">,</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailHtmlContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s2">"/messages/</span><span class="si">{</span><span class="nv">$email</span><span class="o">-&gt;</span><span class="n">id</span><span class="si">}</span><span class="s2">.html"</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="nv">$response</span><span class="o">-&gt;</span><span class="nf">getBody</span><span class="p">(),</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailTextContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s2">"/messages/</span><span class="si">{</span><span class="nv">$email</span><span class="o">-&gt;</span><span class="n">id</span><span class="si">}</span><span class="s2">.plain"</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="nv">$response</span><span class="o">-&gt;</span><span class="nf">getBody</span><span class="p">(),</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailSenderEquals</span><span class="p">(</span><span class="nv">$expected</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s2">"/messages/</span><span class="si">{</span><span class="nv">$email</span><span class="o">-&gt;</span><span class="n">id</span><span class="si">}</span><span class="s2">.json"</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
        <span class="nv">$email</span> <span class="o">=</span> <span class="nb">json_decode</span><span class="p">(</span><span class="nv">$response</span><span class="o">-&gt;</span><span class="nf">getBody</span><span class="p">());</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="nv">$expected</span><span class="p">,</span> <span class="nv">$email</span><span class="o">-&gt;</span><span class="n">sender</span><span class="p">,</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">assertEmailRecipientsContain</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="p">,</span> <span class="nv">$description</span> <span class="o">=</span> <span class="s1">''</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">mailcatcher</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s2">"/messages/</span><span class="si">{</span><span class="nv">$email</span><span class="o">-&gt;</span><span class="n">id</span><span class="si">}</span><span class="s2">.json"</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">send</span><span class="p">();</span>
        <span class="nv">$email</span> <span class="o">=</span> <span class="nb">json_decode</span><span class="p">(</span><span class="nv">$response</span><span class="o">-&gt;</span><span class="nf">getBody</span><span class="p">());</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="nv">$needle</span><span class="p">,</span> <span class="nv">$email</span><span class="o">-&gt;</span><span class="n">recipients</span><span class="p">,</span> <span class="nv">$description</span><span class="p">);</span>
    <span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The <a href="https://gist.github.com/DavertMik/7969053">complete code listing</a> is published as gist.</p>

<h2 id="example">Example</h2>

<p>How might a test using this <code class="language-plaintext highlighter-rouge">EmailTestCase</code> look?</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>		
	<span class="k">function</span> <span class="n">testNotificationIsSent</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="c1">// ... trigger notifications</span>

        <span class="nv">$email</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getLastMessage</span><span class="p">();</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEmailSenderEquals</span><span class="p">(</span><span class="s1">'&lt;bugira@bugira.com&gt;'</span><span class="p">,</span> <span class="nv">$email</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEmailRecipientsContain</span><span class="p">(</span><span class="s1">'&lt;davert@ukr.net&gt;'</span><span class="p">,</span> <span class="nv">$email</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEmailSubjectEquals</span><span class="p">(</span><span class="s1">'[Bugira] Ticket #2 has been closed'</span><span class="p">,</span> <span class="nv">$email</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEmailSubjectContains</span><span class="p">(</span><span class="s1">'Ticket #2'</span><span class="p">,</span> <span class="nv">$email</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEmailHtmlContains</span><span class="p">(</span><span class="s1">'#2 integer pede justo lacinia eget tincidunt'</span><span class="p">,</span> <span class="nv">$email</span><span class="p">);</span>
    <span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>We now have a really simple class for testing emails from your application. Ok, that’s not a unit test. For unit testing you should use a mocking framework to fake the delivery in your PHP code. But you can use this class in acceptance tests (with Selenium) or integration tests. It is much simpler to test emails this way, than to dig into the internals of your email sending library and define mocks. The drawbacks here are the usage of  standalone daemon, and reconfiguring your application to use its SMTP server.</p>

<hr />

<p>It looks like this post is long enough to be published. We will continue email testing next time with Codeception framework. We will develop <code class="language-plaintext highlighter-rouge">EmailHelper</code> class for scenario-driven tests of Codeception.</p>

<p><a href="https://gist.github.com/DavertMik/7969053">EmailTestCase Source</a></p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8.1: Minor updates</title>
      <link>https://codeception.com/12-07-2013/codeception-181-minor-updates.html</link>
      <pubDate>Sat, 07 Dec 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/12-07-2013/codeception-181-minor-updates</guid>
      <description><![CDATA[ <p>Codeception 1.8.1 is out. Bugfixes and small useful features in it. The most interesting improvement was done by <strong>frqnck</strong>. Phar version now has <code class="language-plaintext highlighter-rouge">self-update</code> command which acts the same way as it is in composer. From now on you can easily upgrade <code class="language-plaintext highlighter-rouge">codeception.phar</code> file.</p>

<p>Small yet important change in WebDriver module. <strong>Default <code class="language-plaintext highlighter-rouge">wait</code> parameter is set to 0</strong>. This was done because Selenium <a href="https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits">implicit waits</a> didn’t work as expected - this parameter slowed down test execution. Browser waited for element even if it was already on a page. Please notice this on upgrading.</p>

<h3 id="changes">Changes</h3>

<ul>
  <li>upgraded to php-webdriver 0.3</li>
  <li>added general <code class="language-plaintext highlighter-rouge">sendAjaxRequest()</code> method to all framework/phpbrowser modules to send ajax requests of any types by <strong>gchaincl</strong>.</li>
  <li>fixed <a href="Wrong URI construction in Yii1 module">URI construction in Yii1</a> module by <strong>kop</strong>(also in 1.7)</li>
  <li><code class="language-plaintext highlighter-rouge">Fixed Yii2 statusCode</code> by <strong>cebe</strong></li>
  <li>fixed: <code class="language-plaintext highlighter-rouge">Placeholder\Registry::unsetRegistry()</code> should only be used with &lt; 2.2.0 by <strong>Bittarman</strong></li>
  <li><code class="language-plaintext highlighter-rouge">waitForElementChange()</code> was fixed in WebDriver module</li>
  <li>fixed <code class="language-plaintext highlighter-rouge">seeLink</code> and <code class="language-plaintext highlighter-rouge">dontSeeLink</code> methods in framework modules by <strong>enumag</strong>.</li>
  <li>added <code class="language-plaintext highlighter-rouge">seeHttpHeaderOnce</code> to REST module for checking if headers appear only once.</li>
  <li>setUpBeforeClass/tearDownAfterClass method will work as they are expected in PHPUnit</li>
  <li><code class="language-plaintext highlighter-rouge">Debug::debug</code> can output any variable in console.</li>
  <li>fixed: “WebDriver <code class="language-plaintext highlighter-rouge">makeScreenshot</code> doesn’t create directories” by <strong>joksnet</strong></li>
  <li>fixed <code class="language-plaintext highlighter-rouge">grabValueFrom</code> method in framework modules (also in 1.7)</li>
  <li>fixed: “Disable remote coverage not work” by <strong>tiger-seo</strong> (also in 1.6, 1.7)</li>
  <li><code class="language-plaintext highlighter-rouge">self-update</code> command added to phar by <strong>frqnck</strong></li>
</ul>

<p><em>Dependencies were updated, thus Symfony components were updated to 2.4. No changes to composer.json was made, so this release is compatible with Symfony 2.3 as well.</em></p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="181">1.8.1</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<h4 id="174">1.7.4</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/1.7.4/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Selenium WebDriver tests with Codeception</title>
      <link>https://codeception.com/11-20-2013/webdriver-tests-with-codeception.html</link>
      <pubDate>Wed, 20 Nov 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-20-2013/webdriver-tests-with-codeception</guid>
      <description><![CDATA[ <p><a href="https://codeception.com/11-12-2013/working-with-phpunit-and-selenium-webdriver.html">Last time</a> we discovered API of new <a href="https://github.com/facebook/php-webdriver">WebDriver PHP</a> bindings. We wrote a basic test in PHPUnit that uses Selenium and Firefox browser to find <code class="language-plaintext highlighter-rouge">php-webdriver</code> library on Github. Today we will reimplement the same test with Codeception.</p>

<h3 id="installation">Installation</h3>

<p>Depending on your preferences you can install Codeception either by downloading <a href="https://codeception.com/thanks.html"><code class="language-plaintext highlighter-rouge">codecept.phar</code></a> archive from the site, or alternatively by using composer.</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"require-dev"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"codeception/codeception"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>With composer you will need to execute:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php composer.phar <span class="nb">install</span></code></pre></figure>

<p>In previous tutorial we did installation using Composer, so in current examples we will be using it as well.</p>

<p>Sure, we also need <a href="https://code.google.com/p/selenium/downloads/detail?name=selenium-server-standalone-2.37.0.jar&amp;can=2&amp;q=selenium-server-standalone-2">Selenium server</a> executable as well. You need Java installed in order to run the Selenium server. You can launch it by running this:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">java <span class="nt">-jar</span> selenium-server-standalone-2.37.0.jar</code></pre></figure>

<p>When all installation steps are done, we can continue with creating Codeception bootstrap.</p>

<h3 id="bootstrap">Bootstrap</h3>

<p>Unlike the phpunit Codeception requires a small bootstrap step. Codeception helps you to organize tests into 3 categories: acceptance, functional, and unit tests. To create all tests and support directories, you will need to run the <code class="language-plaintext highlighter-rouge">bootstrap</code> command.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">vendor/bin/codecept bootstrap</code></pre></figure>

<p>Selenium tests are acceptance tests. So let’s create a skeleton for the basic acceptance test:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">vendor/bin/codecept generate:cept acceptance GitHub</code></pre></figure>

<p>This will create new file in <code class="language-plaintext highlighter-rouge">tests/acceptance/GitHubCept.php</code>. But we need some additional configuration to be done before proceeding. Instead of creating webdriver session in tests manually, we delegate this to Codeception. Codeception will take care for creating session before each test, and closing it after. That’s why Selenium configuration should be written into <code class="language-plaintext highlighter-rouge">tests/acceptance.suite.yml</code>.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">WebGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">WebDriver</span>
        <span class="pi">-</span> <span class="s">WebHelper</span>
    <span class="na">config</span><span class="pi">:</span>
        <span class="na">WebDriver</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s1">'</span><span class="s">https://github.com'</span>
            <span class="na">browser</span><span class="pi">:</span> <span class="s1">'</span><span class="s">firefox'</span></code></pre></figure>

<p>Each time you change configuration in Codeception you should run the <code class="language-plaintext highlighter-rouge">build</code> command.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">vendor/bin/codecept build</code></pre></figure>

<h3 id="writing-a-test">Writing a Test</h3>

<p>Let’s start with something very basic. We will open the Github page and we will make sure that <code class="language-plaintext highlighter-rouge">GitHub</code> word is within the page title.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'see GitHub word in title '</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInTitle</span><span class="p">(</span><span class="s1">'GitHub'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>We are using the <code class="language-plaintext highlighter-rouge">wantTo</code> command just to give a test clean description. <code class="language-plaintext highlighter-rouge">amOnPage</code> command opens browser on the github home page, and all the commands that start with <code class="language-plaintext highlighter-rouge">see</code> are assertions you can use. There are lots of commands in WebGuy class you can use writing the test. All them are taking from corresponging <a href="https://codeception.com/docs/03-ModulesAndHelpers">modules</a>, in our case it is <a href="https://codeception.com/docs/modules/WebDriver">WebDriver</a> module. If you use IDE you can check them all with autocompletion.</p>

<p><img src="/images/webdriver/codecept-wb.png" alt="Codeception Autocomplete" /></p>

<p>But let’s execute a test with <code class="language-plaintext highlighter-rouge">run</code> command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">vendor/bin/codecept run</code></pre></figure>

<p>And you will see this output:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Codeception PHP Testing Framework v1.8.0
Powered by PHPUnit 3.7.28 by Sebastian Bergmann.

Functional Tests <span class="o">(</span>0<span class="o">)</span> <span class="nt">------------------------</span>
<span class="nt">---------------------------------------------</span>

Acceptance Tests <span class="o">(</span>1<span class="o">)</span> <span class="nt">-------------------------------------------</span>
Trying to see github word <span class="k">in </span>title  <span class="o">(</span>GitHubCept.php<span class="o">)</span>       Ok
<span class="nt">----------------------------------------------------------------</span>

Unit Tests <span class="o">(</span>0<span class="o">)</span> <span class="nt">------------------------------</span>
<span class="nt">---------------------------------------------</span>


Time: 21.62 seconds, Memory: 5.00Mb

OK <span class="o">(</span>1 <span class="nb">test</span>, 1 assertion<span class="o">)</span></code></pre></figure>

<p>You may have noticed that Codeception is itself powered by PHPUnit. Basically you can execute native PHPUnit tests inside Codeception, but the main idea of Codeception is scenario driven tests written from an eye of a tester. Each test should descibe user’s actions in simple words: I see, I click, etc. Let’s see how using just this simple terms with no OOP complexity we can write a bit more complex test.</p>

<p>Our test should open github in a browser and use the search form to get to “facebook/php-webdriver” library page.
Before writing the test we did some research of GitHub page to find selectors we can use to match elements on page. This was described in <a href="https://codeception.com/11-12-2013/working-with-phpunit-and-selenium-webdriver.html">previous tutorial</a>.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'find facebook/php-webdriver on GitHub'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'#js-command-bar-field'</span><span class="p">,</span><span class="s1">'php-webdriver'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'#js-command-bar-field'</span><span class="p">,</span> <span class="nc">WebDriverKeys</span><span class="o">::</span><span class="no">ENTER</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'li.public:nth-child(1) &gt; h3:nth-child(3) &gt; a:nth-child(1) &gt; em:nth-child(2)'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInTitle</span><span class="p">(</span><span class="s2">"php-webdriver"</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeCurrentUrlEquals</span><span class="p">(</span><span class="s1">'/facebook/php-webdriver'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>You can execute this test and see it passes. Unlike the classical PHPUnit test, this code does not require comments. It is very clean and easy to understand and edit by anyone a team with basic PHP/HTML/CSS skills.</p>

<h3 id="tips-and-tricks">Tips and Tricks</h3>

<p>In this section we will share some ideas, that you can use in your tests. Sure that would not be the same tips we have in PHPUnit. But in PHPUnit test we wrote a helper function to pause the execution. This helped us to search for required locators. In Codeception (starting from 1.8) we can use <code class="language-plaintext highlighter-rouge">$I-&gt;pauseExecution();</code> method for this. The test will stop the scenario in that place and wait for <code class="language-plaintext highlighter-rouge">Enter</code> to be pressed. Worth to mention, that pauseExecution works only in debug mode (sure, you don’t want to freeze when running tests on CI). So you should pass <code class="language-plaintext highlighter-rouge">--debug</code> option when using it.</p>

<p>But even Codeception provides us with dozen of predefined commands, we might want to access webdriver session by your own. For this we have a <code class="language-plaintext highlighter-rouge">executeInSelenium</code> command:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeInSelenium</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="kt">RemoteWebDriver</span> <span class="nv">$webDriver</span><span class="p">)</span> <span class="p">{</span>
	<span class="nv">$webDriver</span><span class="o">-&gt;</span><span class="nf">getKeyboard</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="nc">WebDriverKeys</span><span class="o">::</span><span class="no">ENTER</span><span class="p">);</span>
<span class="p">});</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>But that doesn’t make our test more readable. What can we do to simplify it a bit?
Well, let’s replace this double search for ‘#js-command-bar-field’ input field. We can use <code class="language-plaintext highlighter-rouge">submitForm</code> command that works for forms on any kind, and you can pass array of field values into it. Current form id is <code class="language-plaintext highlighter-rouge">top_search_form</code>, so we can rewrite our test like:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'find facebook/php-webdriver on GitHub'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">submitForm</span><span class="p">(</span><span class="s1">'#top_search_form'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'q'</span> <span class="o">=&gt;</span> <span class="s1">'php-webdriver'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'li.public:nth-child(1) &gt; h3:nth-child(3) &gt; a:nth-child(1) &gt; em:nth-child(2)'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInTitle</span><span class="p">(</span><span class="s2">"php-webdriver"</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeCurrentUrlEquals</span><span class="p">(</span><span class="s1">'/facebook/php-webdriver'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>When running WebDriver tests with Codeception they may look a bit slower then the same tests run with PHPUnit. 
That’s because Codeception has default delay of 5 seconds for each test action on page. This delay can be set to <code class="language-plaintext highlighter-rouge">0</code> in order to run test faster. This is configured in <code class="language-plaintext highlighter-rouge">acceptance.suite.yml</code></p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">WebGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">WebDriver</span>
        <span class="pi">-</span> <span class="s">WebHelper</span>
    <span class="na">config</span><span class="pi">:</span>
        <span class="na">WebDriver</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s1">'</span><span class="s">https://github.com'</span>
            <span class="na">browser</span><span class="pi">:</span> <span class="s1">'</span><span class="s">firefox'</span>
            <span class="na">wait</span><span class="pi">:</span> <span class="s">0</span></code></pre></figure>

<p>This should execute the same test 30% faster then before. But if your page use JavaScript and Ajax, you should increase the wait time or use various <code class="language-plaintext highlighter-rouge">waitFor</code> commands of WebDriver.</p>

<h2 id="conclusion">Conclusion</h2>

<p>At first sight setting up Codeception Selenium test may look a bit harder then with PHPUnit. At first sight it’s hard to see real benefits in it. But the key idea of Codeception is <strong>to separate the test code and support code</strong>. So you should write only tests, and most of helper methods was already written for you. Thus, the test is kept clean and readable. It is easy to change and easy to manage. If you want to switch a browser, you should not edit a test, but change the configuration. You want to execute test in 2 browsers one by one? No problems, just change a configuration.</p>

<p>Codeception is very flexible framework that you can use to write your Selenium tests. After all it’s really simple and fun.</p>

<p>Source file of this tutorial <a href="https://github.com/DavertMik/codeception-webdriver-demo">are available on GitHub</a>.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.8: Phalcon, Environments, DataProviders</title>
      <link>https://codeception.com/11-15-2013/codeception-18-phalcon-environments-dataproviders.html</link>
      <pubDate>Fri, 15 Nov 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-15-2013/codeception-18-phalcon-environments-dataproviders</guid>
      <description><![CDATA[ <p>This release brings lots of changes. Finally we got working DataProviders (the issue was opened for about a year), and <code class="language-plaintext highlighter-rouge">@depends</code> tag. But the details below. Let’s start with the most important new features:</p>

<h2 id="phalcon-framework-support">Phalcon Framework Support</h2>

<p><img src="https://lh3.googleusercontent.com/-wjtJgs6HLwc/AAAAAAAAAAI/AAAAAAAAAD4/IvimRkefmI4/s120-c/photo.jpg" alt="Phalcon" style="float: right" /></p>

<p><a href="https://phalcon.io/">Phalcon</a> is the fastest PHP framework in the world. And that’s not just a marketing slogan. Phalcon was developed as C extension, so it is already precompiled and loads into memory only once. Phalcon is modern framework with DI container, ORM (inspired by Doctrine), and templating engine (inspired by Twig). It is one of the most innovative projects in PHP world, so you should at least check it out.</p>

<p>If you already work with Phalcon, here is a good news for you. Codeception got <a href="https://codeception.com/docs/modules/Phalcon1">Phalcon1</a> module, that allows you to write functional tests with minimum setup. Besides standard framework interface this module provides actions for session and database access. It also wraps all tests into nested transactions, and rollbacks them in the end. Thus, all your database tests run superfast.</p>

<p>Is there any Phalcon project tested with Codeception? Yes, it is the official <a href="https://github.com/phalcon/forum">Phalcon’s forum</a>.</p>

<p>This module was developed by <strong>cujo</strong> and improved by <strong>davert</strong>. We hope you like it.</p>

<h2 id="environments">Environments</h2>

<p>This is something you might not expect in the form it was produced, but, probably, that was long awaited.
This is to run tests multiple times over different environments. The most common issue is running acceptance tests over different browsers: firefox, phantomjs, chrome. Now you can create 3 different configurations and you can get tests will be repeated 3 times: in firefox, in phantomjs, and in chrome. The second usecase is run tests over different databases.</p>

<p>Feature is pretty straightforward in use. You define the name of environment below the <code class="language-plaintext highlighter-rouge">env</code> key, and then you redefine any of configuration values you need.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="err">```</span> <span class="s">yaml</span>
<span class="na">class_name</span><span class="pi">:</span> <span class="s">WebGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">WebDriver</span>
        <span class="pi">-</span> <span class="s">WebHelper</span>
    <span class="na">config</span><span class="pi">:</span>
        <span class="na">WebDriver</span><span class="pi">:</span>
            <span class="na">url</span><span class="pi">:</span> <span class="s1">'</span><span class="s">http://127.0.0.1:8000/'</span>
            <span class="na">browser</span><span class="pi">:</span> <span class="s1">'</span><span class="s">firefox'</span>

<span class="na">env</span><span class="pi">:</span>
    <span class="na">phantom</span><span class="pi">:</span>
         <span class="na">modules</span><span class="pi">:</span>
            <span class="na">config</span><span class="pi">:</span>
                <span class="na">WebDriver</span><span class="pi">:</span>
                    <span class="na">browser</span><span class="pi">:</span> <span class="s1">'</span><span class="s">phantomjs'</span></code></pre></figure>

<p><a href="https://codeception.com/docs/07-AdvancedUsage#Environments">Advanced Usage</a> chapter was updated.</p>

<h2 id="dataproviders">DataProviders</h2>

<p>You can use PHPUnit dataproviders in <code class="language-plaintext highlighter-rouge">Codeception\TestCase\Test</code> files. Yep. Finally.</p>

<p>Probably DataProviders are not really readable, as you need always to refer into data sets, which may be defined in the different part of a testcase. You can consider using <a href="https://github.com/Codeception/Specify#examples">examples of Codeception\Specify</a> library, as for alternative for dataproviders.</p>

<p>Is there a way you can use data providers in scenario driven test? Not exactly, but you can emulate them with loops and conditional asserts:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$posts</span> <span class="k">as</span> <span class="nv">$post</span><span class="p">)</span> <span class="p">{</span>
	<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">canSee</span><span class="p">(</span><span class="nv">$post</span><span class="o">-&gt;</span><span class="n">title</span><span class="p">,</span><span class="s1">'.post h2'</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="depends">Depends</h2>

<p>Declare depending tests in Cest and Test files. Works just as the original <code class="language-plaintext highlighter-rouge">@depends</code> of PHPUnit.
In Cests you can combine this with <code class="language-plaintext highlighter-rouge">@before</code> annotation. More information in <a href="https://codeception.com/docs/07-AdvancedUsage">Advanced Usage</a>.</p>

<h2 id="debug">Debug</h2>

<p>Debug output was refactored, and moved out to <code class="language-plaintext highlighter-rouge">Codeception\Util\Debug</code> class. This class can be used globally, i.e in tests, helpers, - wherever you want. To print debug information you should call:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="nc">Codeception\Util\Debug</span><span class="p">;</span>
<span class="nc">Debug</span><span class="o">::</span><span class="nf">debug</span><span class="p">(</span><span class="s2">"This is working"</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This change dramatically improves debug output. You can also pause execution with <code class="language-plaintext highlighter-rouge">pause</code> static method of this class. Useful for debugging and tests development, implemented in <code class="language-plaintext highlighter-rouge">WebDriver</code> module as <code class="language-plaintext highlighter-rouge">pauseExecution</code> action.</p>

<h2 id="bugfixes-and-minor-changes">Bugfixes and Minor Changes</h2>

<ul>
  <li>WebDriver module got <code class="language-plaintext highlighter-rouge">pauseExecution</code> method which pauses running test in debug mode.</li>
  <li>Generated PageObject file <code class="language-plaintext highlighter-rouge">URL</code> const was changed to static variable.</li>
  <li>
    <table>
      <tbody>
        <tr>
          <td><code class="language-plaintext highlighter-rouge">waitForElementChange()</code> callback return value was not being used by <strong>wheelsandcogs</strong></td>
          <td>also in 1.7</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>bugfix for making screenshots with WebDriver by <strong>Michael Wang</strong>.</td>
          <td>also in 1.7</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>Doctrine2: handle NULL value in seeInRepository param array by <strong>imanzuk</strong></td>
          <td>also in 1.7</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>REST: fix adding parameters to url to non-GET HTTP methods by <strong>sheershoff</strong></li>
  <li>REST: Added <code class="language-plaintext highlighter-rouge">sendOPTIONS()</code> and <code class="language-plaintext highlighter-rouge">sendHEAD()</code> requests for CORS testing by <strong>elazar</strong></li>
  <li>Symfony2: fixed usage of profiler</li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>Strict declaratin error fixes for framework constraints</td>
          <td>also in 1.6, 1.7</td>
        </tr>
      </tbody>
    </table>
  </li>
</ul>

<h2 id="update">Update</h2>

<p><strong>Warning</strong>. Module <code class="language-plaintext highlighter-rouge">Unit</code> was deprecated in 1.6 and was removed in 1.8. Please disable it in <code class="language-plaintext highlighter-rouge">unit.suite.yml</code> if you were using it. If you see this error:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Codeception PHP Testing Framework v1.8.0
Powered by PHPUnit 3.7.28 by Sebastian Bergmann.



  <span class="o">[</span>Codeception<span class="se">\E</span>xception<span class="se">\C</span>onfiguration]
  Unit could not be found and loaded</code></pre></figure>

<p>Just disable <code class="language-plaintext highlighter-rouge">Unit</code> module. Thanks</p>

<p>If you prefer stability over features you can stay on 1.7 or 1.6 releases. We’ve got them updated too.</p>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="180">1.8.0</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<h4 id="173">1.7.3</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/1.7.3/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<h4 id="1612">1.6.12</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/1.6.12/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<h2 id="what-to-expect-from-20">What to expect from 2.0</h2>

<p>It is almost 2 years of Codeception, and we are planning to release 2.0 version as a next major to celebrate that. It is a major change, thus we can add few BC breaks. We are planning to:</p>

<ul>
  <li>move to PHP 5.4. Not really necessary, yet it is getting hard to support 5.3.</li>
  <li>remove Mink entirely in favor of WebDriver for browser-testing and Goutte for headless testing.</li>
  <li>remove 2-times test execution (finally!).</li>
  <li>??? (proposed by you)</li>
</ul>

 ]]></description>
    </item>
    
    <item>
      <title>Working with PHPUnit and Selenium Webdriver </title>
      <link>https://codeception.com/11-12-2013/working-with-phpunit-and-selenium-webdriver.html</link>
      <pubDate>Tue, 12 Nov 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-12-2013/working-with-phpunit-and-selenium-webdriver</guid>
      <description><![CDATA[ <p>In this post we will explore some basics of user acceptance testing with <strong>Selenium</strong>. We will do this with classical unit testing framework PHPUnit, web browser Firefox, and with new <a href="https://github.com/facebook/php-webdriver">php-webdriver</a> library recently developed by Facebook.</p>

<p>Selenium allows us to record user actions that we do inside a browser and then automate them. PHPUnit will be used to do various assertions and check them for fallacy. And <code class="language-plaintext highlighter-rouge">php-webdriver</code> is used to connect PHP with Selenium, in order to do browser manipulation in PHP.</p>

<p>Probably you know, that PHPUnit itself can do Selenium manipulations via PHPUnit. There is <a href="https://phpunit.de/manual/3.7/en/selenium.html">PHPUnit_Selenium</a> extension you may use. We will use php-webdriver instead because this implementation is modern and its API is more clean and looks much the same way as original Java Selenium API. That’s why it is easier to learn, and much powerful, then the PHPUnit’s one. For example, it allows you use send native touch events, which is important in era of mobile-ready web applications.</p>

<h3 id="grab-the-tools">Grab the tools</h3>

<p>Let’s install all the required tools using <a href="https://packagist.org">Composer</a>. For this we will need to have <code class="language-plaintext highlighter-rouge">composer.json</code> file created:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"require-dev"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"phpunit/phpunit"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"facebook/webdriver"</span><span class="p">:</span><span class="w"> </span><span class="s2">"dev-master"</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>We won’t develop any application, thus we are ok, with <code class="language-plaintext highlighter-rouge">require-dev</code> section only. Let’s run</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php composer.phar <span class="nb">install</span></code></pre></figure>

<p>and grab the latest versions of both libraries. We also will need <a href="https://code.google.com/p/selenium/downloads/detail?name=selenium-server-standalone-2.37.0.jar&amp;can=2&amp;q=selenium-server-standalone-2">Selenium server</a> executable as well. You need Java installed in order to run the Selenium server. You can launch it by running this:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">java <span class="nt">-jar</span> selenium-server-standalone-2.37.0.jar</code></pre></figure>

<p>And when the tools are prepared, let’s write some tests.</p>

<h3 id="phpunit-test">PHPUnit Test</h3>

<p>So let’s try to test something in the web. Let’s start with something simple and well known, like Github. So, let’s create a file and call it <code class="language-plaintext highlighter-rouge">GitHubTest</code>.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTests</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As any PHPUnit test it should extend <code class="language-plaintext highlighter-rouge">PHPUnit_Framework_TestCase</code> (as it was mentioned, we are not using PHPUnit_Extensions_Selenium2TestCase here). For every test we will need to launch a browser, or in other words, we are starting a Selenium session. This is done by creating <code class="language-plaintext highlighter-rouge">RemoteWebDriver</code> instance:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTests</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This initialization part is taken from php-webdriver README file. We don’t have any test yet, so let’s write something a very basic. Something like: “If I open https://github.com, page title should contain GitHub”.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">protected</span> <span class="nv">$url</span> <span class="o">=</span> <span class="s1">'https://github.com'</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testGitHubHome</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>
        <span class="c1">// checking that page title contains word 'GitHub'</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="s1">'GitHub'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getTitle</span><span class="p">());</span>
    <span class="p">}</span>    

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Now we execute our first test with phpunit</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">vendor/bin/phpunit GitHubTest.php</code></pre></figure>

<p>and in a few seconds we should see a Firefox window with Github Page in it</p>

<p><img src="/images/webdriver/WebDriverStart.png" alt="Opening web page with PHPUnit and Selenium" /></p>

<p><em>please notice the WebDriver text in the status bar, this tells you that this browser window is controlled by WebDriver</em>.</p>

<p>In a console we will see this output:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">PHPUnit 3.7.28 by Sebastian Bergmann.


<span class="nb">.</span>

Time: 19.44 seconds, Memory: 1.75Mb

OK <span class="o">(</span>1 <span class="nb">test</span>, 1 assertion<span class="o">)</span></code></pre></figure>

<p>We will see that test has finished, but the browser window stays opened. That is because we did not implement a <code class="language-plaintext highlighter-rouge">tearDown</code> method, that should be used to close the webdriver session:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">tearDown</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">quit</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="advanced-test">Advanced Test</h2>

<p>We didn’t touch any of page elements in a previous test. We just opened the page and checked its title. But the power of webdriver reveals when you want to click elements, fill forms, drag and drop elements, etc. That’s why we will write a test that demonstrates some of this features.</p>

<p>But how can control the browser? Should we move the mouse in order to click on element? Well, not exactly. WebDriver allows us to locate element on page by its ID, class name, element name, CSS, or XPath. Let’s list all possible locator types, taken from <code class="language-plaintext highlighter-rouge">WebDriverBy</code> class:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::className()</code> - searches for element by its CSS class.</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::cssSelector()</code> - searches for element by its CSS selector (like jQuery).</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::id()</code> - searches for element by its id.</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::linkText()</code> - searches for a link whose visible text equals to the value provided.</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::partialLinkText()</code> - same as above, but link partly contain the value.</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::tagName()</code> - search for element by its tag name.</li>
  <li><code class="language-plaintext highlighter-rouge">WebDriverBy::xpath()</code> - search for element by xpath. The most complex, yet, most powerful way for element location.</li>
</ul>

<p>To find element we should use <code class="language-plaintext highlighter-rouge">webDriver-&gt;findElement</code> method, with locator specified with <code class="language-plaintext highlighter-rouge">WebDriverBy</code>.</p>

<p>After the matched element is found we can click on it. Like this:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">tearDown</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">close</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testSearch</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>
        <span class="c1">// find search field by its id</span>
        <span class="nv">$search</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElement</span><span class="p">(</span><span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">id</span><span class="p">(</span><span class="s1">'js-command-bar-field'</span><span class="p">));</span>
        <span class="nv">$search</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">();</span>
	<span class="p">}</span>    
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><img src="/images/webdriver/WebDriverSearch.png" alt="Locating Web Element in Firefox" /></p>

<p>We are clicking the GitHub global search field, located in top menu bar, matched by its id. By the way, how did we get the element’s id? That’s a good question. Searching for element locators is the most important task in acceptance testing. For every test we need to get the elements that are involved in it. Let’s show some simple tricks that will definitely help you in writing complex acceptance tests.</p>

<h2 id="locating-elements-tips--tricks">Locating Elements: Tips &amp; Tricks</h2>

<p>The first thing we can do is to pause the test execution. While browser window is still open, we can use it to find the locator. To pause the test execution lets write this helper method inside a test class:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="k">protected</span> <span class="k">function</span> <span class="n">waitForUserInput</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="nb">trim</span><span class="p">(</span><span class="nb">fgets</span><span class="p">(</span><span class="nb">fopen</span><span class="p">(</span><span class="s2">"php://stdin"</span><span class="p">,</span><span class="s2">"r"</span><span class="p">)))</span> <span class="o">!=</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">13</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>If we use it somewhere in our tests, PHPUnit will wait for <code class="language-plaintext highlighter-rouge">Enter</code> key pressed in console before going on.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">testSearch</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">waitForUserInput</span><span class="p">();</span> <span class="c1">// paused       </span>
    <span class="p">}</span>    
<span class="cp">?&gt;</span></code></pre></figure>

<p>Now when the browser window is opened we are free to search for required element with no hurry. We are using Firfox Developer Tools for that. With the Element Inspector within we can point to element and get its unique CSS locator.</p>

<p><img src="/images/webdriver/WebDriverSelector.png" alt="Using WebDriver with PHPUnit to test GitHub" /></p>

<p>That is how we got search field id: <code class="language-plaintext highlighter-rouge">#js-command-bar-field</code>. Doing the sample steps, let’s continue writing our test and find <code class="language-plaintext highlighter-rouge">php-webdriver</code> repository on GitHub.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="k">protected</span> <span class="nv">$url</span> <span class="o">=</span> <span class="s1">'https://github.com'</span><span class="p">;</span>
    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">tearDown</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">close</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testSearch</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>
        
        <span class="c1">// find search field by its id</span>
        <span class="nv">$search</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElement</span><span class="p">(</span><span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">id</span><span class="p">(</span><span class="s1">'js-command-bar-field'</span><span class="p">));</span>
        <span class="nv">$search</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">();</span>
        
        <span class="c1">// typing into field</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getKeyboard</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">sendKeys</span><span class="p">(</span><span class="s1">'php-webdriver'</span><span class="p">);</span>
        
        <span class="c1">// pressing "Enter"</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getKeyboard</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="nc">WebDriverKeys</span><span class="o">::</span><span class="no">ENTER</span><span class="p">);</span>
        
        <span class="nv">$firstResult</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElement</span><span class="p">(</span>
            <span class="c1">// some CSS selectors can be very long:</span>
            <span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">cssSelector</span><span class="p">(</span><span class="s1">'li.public:nth-child(1) &gt; h3:nth-child(3) &gt; a:nth-child(1) &gt; em:nth-child(2)'</span><span class="p">)</span>
        <span class="p">);</span>
        
        <span class="nv">$firstResult</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">();</span>
        
        <span class="c1">// we expect that facebook/php-webdriver was the first result</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="s2">"php-webdriver"</span><span class="p">,</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getTitle</span><span class="p">());</span>
        
        <span class="c1">// checking current url</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span>
        	<span class="s1">'https://github.org/facebook/php-webdriver'</span><span class="p">,</span> 
        	<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getCurrentURL</span><span class="p">()</span>
        <span class="p">);</span>
    <span class="p">}</span>


    <span class="k">protected</span> <span class="k">function</span> <span class="n">waitForUserInput</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="nb">trim</span><span class="p">(</span><span class="nb">fgets</span><span class="p">(</span><span class="nb">fopen</span><span class="p">(</span><span class="s2">"php://stdin"</span><span class="p">,</span><span class="s2">"r"</span><span class="p">)))</span> <span class="o">!=</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">13</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>If we run this test we will see that it is failing on the last step:</p>

<p><img src="/images/webdriver/WebDriverFail.png" alt="PHPUnit Test is Failing on Assertion" /></p>

<p>That’s because we forgot that GitHub uses <code class="language-plaintext highlighter-rouge">https</code> by default, and GitHub is a company and not a non-profit  organization (as we used to think of it, he-he). Though let’s change the expected url to ‘https://github.com/facebook/php-webdriver’ and see the test is passing.</p>

<h2 id="element-not-found">Element Not Found</h2>

<p>Probably we will also want to check if element is located on a page. If we were using <code class="language-plaintext highlighter-rouge">Selenium2TestCase</code> of PHPUnit, we would have several nice assertion that we can use just for that. In case of php-webdriver library we will need to implement them on our own. But that’s pretty easy. Php-Webdriver throws various <a href="https://github.com/facebook/php-webdriver/blob/master/lib/WebDriverExceptions.php">exceptions</a>, which we can handle and transform into PHPUnit’s assertions:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="k">protected</span> <span class="k">function</span> <span class="n">assertElementNotFound</span><span class="p">(</span><span class="nv">$by</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$els</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElements</span><span class="p">(</span><span class="nv">$by</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$els</span><span class="p">))</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">fail</span><span class="p">(</span><span class="s2">"Unexpectedly element was found"</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="c1">// increment assertion counter</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>        
    <span class="p">}</span>

<span class="cp">?&gt;</span></code></pre></figure>

<p>You can create similar assertion just in the same manner.</p>

<p>We will use newly created <code class="language-plaintext highlighter-rouge">assertElementNotFound</code> method to check that there is no user avatar on “facebook/php-webdriver” page.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">GitHubTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

    <span class="k">protected</span> <span class="nv">$url</span> <span class="o">=</span> <span class="s1">'https://github.com'</span><span class="p">;</span>
    <span class="cd">/**
     * @var \RemoteWebDriver
     */</span>
    <span class="k">protected</span> <span class="nv">$webDriver</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$capabilities</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverCapabilityType</span><span class="o">::</span><span class="no">BROWSER_NAME</span> <span class="o">=&gt;</span> <span class="s1">'firefox'</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span> <span class="o">=</span> <span class="nc">RemoteWebDriver</span><span class="o">::</span><span class="nf">create</span><span class="p">(</span><span class="s1">'http://localhost:4444/wd/hub'</span><span class="p">,</span> <span class="nv">$capabilities</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">tearDown</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">close</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testGitHubHome</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>
        <span class="c1">// checking that page title contains word 'GitHub'</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="s1">'GitHub'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getTitle</span><span class="p">());</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testSearch</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">url</span><span class="p">);</span>

        <span class="c1">// find search field by its id</span>
        <span class="nv">$search</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElement</span><span class="p">(</span><span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">id</span><span class="p">(</span><span class="s1">'js-command-bar-field'</span><span class="p">));</span>
        <span class="nv">$search</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">();</span>

        <span class="c1">// typing into field</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getKeyboard</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">sendKeys</span><span class="p">(</span><span class="s1">'php-webdriver'</span><span class="p">);</span>

        <span class="c1">// pressing "Enter"</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getKeyboard</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="nc">WebDriverKeys</span><span class="o">::</span><span class="no">ENTER</span><span class="p">);</span>

        <span class="nv">$firstResult</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElement</span><span class="p">(</span>
            <span class="c1">// some CSS selectors can be very long:</span>
            <span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">cssSelector</span><span class="p">(</span><span class="s1">'li.public:nth-child(1) &gt; h3:nth-child(3) &gt; a:nth-child(1) &gt; em:nth-child(2)'</span><span class="p">)</span>
        <span class="p">);</span>

        <span class="nv">$firstResult</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">();</span>

        <span class="c1">// we expect that facebook/php-webdriver was the first result</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="s2">"php-webdriver"</span><span class="p">,</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getTitle</span><span class="p">());</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="s1">'https://github.com/facebook/php-webdriver'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">getCurrentURL</span><span class="p">());</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertElementNotFound</span><span class="p">(</span><span class="nc">WebDriverBy</span><span class="o">::</span><span class="nf">className</span><span class="p">(</span><span class="s1">'avatar'</span><span class="p">));</span>

    <span class="p">}</span>

    <span class="k">protected</span> <span class="k">function</span> <span class="n">waitForUserInput</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="nb">trim</span><span class="p">(</span><span class="nb">fgets</span><span class="p">(</span><span class="nb">fopen</span><span class="p">(</span><span class="s2">"php://stdin"</span><span class="p">,</span><span class="s2">"r"</span><span class="p">)))</span> <span class="o">!=</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">13</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">protected</span> <span class="k">function</span> <span class="n">assertElementNotFound</span><span class="p">(</span><span class="nv">$by</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$els</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">webDriver</span><span class="o">-&gt;</span><span class="nf">findElements</span><span class="p">(</span><span class="nv">$by</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$els</span><span class="p">))</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">fail</span><span class="p">(</span><span class="s2">"Unexpectedly element was found"</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="c1">// increment assertion counter</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
        
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="refactoring">Refactoring</h2>

<p>To clean up some things we will separate test methods and support methods. It is a good idea to <strong>move custom assertions into trait</strong>: <code class="language-plaintext highlighter-rouge">WebDriverAssertions</code>. And the pause switcher <code class="language-plaintext highlighter-rouge">waitForUserInput</code> can be moved into <code class="language-plaintext highlighter-rouge">WebDriverDevelop</code> trait. We can enable this trait in a test class, when we develop a test, and turn it off once we finished.</p>

<p>The complete demo project, after this basic refactoring, you can <a href="https://github.com/DavertMik/php-webdriver-demo">find on GitHub</a>.</p>

<h2 id="and-what-about-codeception">And what about Codeception?</h2>

<p>So you did notice that this is Codeception blog. But we didn’t use <a href="https://codeception.com">Codeception framework</a> at all in this tutorial. Sure, we need to mention, that Codeception includes php-webdriver library and <a href="https://codeception.com/docs/modules/WebDriver">WebDriver</a> module out of the box starting from version 1.7. In Codeception you can perform all the web manipulations in a <a href="https://codeception.com/docs/03-AcceptanceTests">much simpler manner using the WebGuy APIs</a>. If you use Codeception you don’t need to implement your own WebDriver assertions nor write boilerplate code.</p>

<h2 id="conclusions">Conclusions</h2>

<p>No matter you are using Codeception or not it is a good idea to understand how to perform browser based acceptance testing using just the php-webdriver by itself. Php-webdriver library provides very clean and flexible APIs you will enjoy working with.</p>

<p>PHP is a language popular for web development, but not for web testing. Test automation engineers prefer Java and Ruby over it. And there is a serious reason for that. There is no such thing like “official Selenium bindings” for PHP, i.e. there is no Selenium client library for PHP created by Selenium team. Developers of <a href="https://github.com/facebook/php-webdriver">php-webdriver</a> get very close to the official Selenium client APIs. That’s why you should use php-webdriver - it really feels and works like native and official Selenium libraries. That is especially important if you have an experience writing acceptance tests in Java or Ruby. Moving to PHP is not that hard, when all the APIs are the same.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.7.2</title>
      <link>https://codeception.com/11-01-2013/codeception-172.html</link>
      <pubDate>Fri, 01 Nov 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-01-2013/codeception-172</guid>
      <description><![CDATA[ <p>So here is November and a new release with a minor changes is here.
The development on 1.8 branch is started and you will get some of a long awaited features soon as well as <a href="https://phalconphp.com/">Phalcon</a>. Btw, you can already try <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Module/Phalcon1.php">Phalcon module</a> for functional testing (yes, its in master branch, and not inclued in phar yet).</p>

<p>Bugfixes:</p>

<ul>
  <li>Updated to be able to use <code class="language-plaintext highlighter-rouge">seeOptionIsSelected</code> and <code class="language-plaintext highlighter-rouge">dontSeeOptionIsSelected</code> by label in framework modules by <strong>piccagliani</strong></li>
  <li>Update to appendField function to handle checkbox value or label by <strong>allmyitjason</strong></li>
  <li>Removed default delay WebDriver <strong>allmyitjason</strong></li>
  <li>better error description whenever config file could not be found by <strong>tiger-seo</strong>.</li>
  <li>Added <code class="language-plaintext highlighter-rouge">appendField</code> function into WebDriver by <strong>allmyitjason</strong></li>
  <li>switched to use <code class="language-plaintext highlighter-rouge">getInternalResponse</code> in frameworks modules. Fixes “PHP Fatal error:  Call to undefined method **\Response::getStatus() “ in Symfony2, Laravel4.</li>
  <li>Fixed PhpBrowser module persisting HTTP authentication between tests by <strong>elazar</strong></li>
  <li>Hardcoded ‘localhost’ removed for Yii1 by <strong>kop</strong></li>
  <li>CodeCoverage works for WebDriver module as well by <strong>allmyitjason</strong></li>
  <li>Improved output formatting for unit tests by <strong>davert</strong></li>
</ul>

<p>Some of this fixes were also added into 1.6.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="172">1.7.2</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<h4 id="1611">1.6.11</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/1.6.10/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>1.7: Bugfix release</title>
      <link>https://codeception.com/10-17-2013/bugfix-release.html</link>
      <pubDate>Thu, 17 Oct 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-17-2013/bugfix-release</guid>
      <description><![CDATA[ <p>The release of 1.7 added new WebDriver module as well as rewritten Output component. Some if changes where major and was not tested for all crucial cases. If you feel comfortable with 1.6 you can stay on 1.6 branch.
But If you want to get more features with some instabilities - connect to 1.7</p>

<h2 id="bugfixes-in-171">Bugfixes in 1.7.1</h2>

<ul>
  <li>error and failures are now displayed correctly with improved stack traces.</li>
  <li>fix for module before/after hooks in Codeception\TestCase\Test.</li>
  <li>select option in WebDriver throws readable message</li>
  <li>wait in WebDriver throws exception when receives 1000 seconds.</li>
</ul>

<h2 id="bugfixes-in-1610-also-in-17">Bugfixes in 1.6.10 (also in 1.7)</h2>

<ul>
  <li>Fix the problem when the method getPort() return 443 80 or null by <strong>thbourlove</strong>.</li>
  <li>Notifies about CURL not installed.</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<h4 id="171">1.7.1</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<h4 id="1610">1.6.10</h4>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/releases/1.6.10/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.7: WebDriver</title>
      <link>https://codeception.com/10-11-2013/codeception-17-webdriver.html</link>
      <pubDate>Fri, 11 Oct 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-11-2013/codeception-17-webdriver</guid>
      <description><![CDATA[ <p>This is new Codeception with awaited <strong>WebDriver</strong> module in it. WebDriver module is new incarnation of Selenium implementation. As it was mentioned in <a href="https://codeception.com/08-29-2013/codeception-sequences-new-webdriver.html">previous post</a> this WebDriver module is based on <a href="https://github.com/facebook/php-webdriver">facebook/php-webdriver</a> bindings. The most valuable thing in new Selenium bindings that they can be used just the same way Selenium is used in Java. It’s very important project for PHP community, and we say “thank you” to all the Facebook behind it. One day PHP will be used in acceptance testing as widely as Java or Ruby is used.</p>

<h2 id="webdriver">WebDriver</h2>

<p>WebDriver module is pretty new, yet you may want to switch to it from Selenium2. It uses just the same interface, so migration should come smoothly. If you have issues, then no hurry, stay with Selenium2 for a while. Let’s list a few features that WebDriver module has:</p>

<h3 id="implicit-waits">Implicit waits</h3>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">waitForText</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span> <span class="c1">// secs</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">waitForElement</span><span class="p">(</span><span class="s1">'#agree_button'</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">waitForElementChange</span><span class="p">(</span><span class="s1">'#menu'</span><span class="p">,</span> <span class="k">function</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriverElement</span> <span class="nv">$el</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nv">$el</span><span class="o">-&gt;</span><span class="nf">isDisplayed</span><span class="p">();</span>
<span class="p">},</span> <span class="mi">100</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">waitForJS</span><span class="p">(</span><span class="s2">"return $.active == 0;"</span><span class="p">,</span> <span class="mi">60</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h3 id="better-keyboard-manipoluation">Better Keyboard Manipoluation</h3>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// &lt;input id="page" value="old" /&gt;</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'#page'</span><span class="p">,</span><span class="s1">'a'</span><span class="p">);</span> <span class="c1">// =&gt; olda</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'#page'</span><span class="p">,</span><span class="k">array</span><span class="p">(</span><span class="s1">'ctrl'</span><span class="p">,</span><span class="s1">'a'</span><span class="p">),</span><span class="s1">'new'</span><span class="p">);</span> <span class="c1">//=&gt; new</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'#page'</span><span class="p">,</span><span class="k">array</span><span class="p">(</span><span class="s1">'shift'</span><span class="p">,</span><span class="s1">'111'</span><span class="p">),</span><span class="s1">'1'</span><span class="p">,</span><span class="s1">'x'</span><span class="p">);</span> <span class="c1">//=&gt; old!!!1x</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'descendant-or-self::*[@id='</span><span class="n">page</span><span class="s1">']'</span><span class="p">,</span><span class="s1">'u'</span><span class="p">);</span> <span class="c1">//=&gt; old!!!1xu</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">pressKey</span><span class="p">(</span><span class="s1">'#name'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'ctrl'</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">),</span> <span class="nc">WebDriverKeys</span><span class="o">::</span><span class="no">DELETE</span><span class="p">);</span> <span class="c1">//=&gt;''</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h3 id="submitform">submitForm</h3>

<p>A submit form method was implemented in WebDriver.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">submitForm</span><span class="p">(</span><span class="s1">'#login'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'login'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">,</span> <span class="s1">'password'</span> <span class="o">=&gt;</span> <span class="s1">'123456'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h3 id="common-selenium-api">Common Selenium API</h3>

<p>Thus If you got any Selenium questions any answers on StackOverflow will help you.
PHP implementation is so close to Java that you can use any answer in PHP.</p>

<p>You can invoke WebDriver methods directly with <code class="language-plaintext highlighter-rouge">executeInSelenium</code></p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeInSelenium</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriver</span> <span class="nv">$webdriver</span><span class="p">)</span> <span class="p">{</span>
  <span class="nv">$webdriver</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s1">'https://google.com'</span><span class="p">);</span>
<span class="p">});</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="symfony-output">Symfony Output</h2>

<p>You will notice a better output formatting in your console.
That’s because we migrated to Symfony Console output. 
As you may know, Symfony console has 3 levels of verbosity, that can set via <code class="language-plaintext highlighter-rouge">-v</code> option.
Codeception now support them. If you want to get all available information about test, run with <code class="language-plaintext highlighter-rouge">-vvv</code> option.
The <code class="language-plaintext highlighter-rouge">--debug</code> option is now equivalent for running <code class="language-plaintext highlighter-rouge">-vv</code>. That’s right, you can get even more information with <code class="language-plaintext highlighter-rouge">vvv</code>. The output will be improved during the development of 1.7 branch. We hope to get completely different output depending on level of verbosity set.</p>

<h2 id="cest-annotations">Cest Annotations</h2>

<p>Cests are now much smarter then they were before. 
If you were using StepObject you might wondered how can you pass step object class into it. 
That was not really obvious, as by default you get Guy class defined in config.
But now you can use <code class="language-plaintext highlighter-rouge">guy</code> annotation to specify which guy class to use.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="cd">/**
 * @guy WebGuy\AdminSteps
 */</span>
<span class="kd">class</span> <span class="nc">AdminCest</span> <span class="p">{</span>

	<span class="k">function</span> <span class="n">banUser</span><span class="p">(</span><span class="kt">WebGuy</span><span class="err">\</span><span class="nc">AdminSteps</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="c1">// ...</span>
	<span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Alternatively you can use <code class="language-plaintext highlighter-rouge">guy</code> annotation for the method itself.</p>

<p>Also you can now use <code class="language-plaintext highlighter-rouge">before</code> and <code class="language-plaintext highlighter-rouge">after</code> annotations to define whic methods of Cest class should be executed before the current one. Thus you can move similar actions into protected methods and invoke them via annotations.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">ModeratorCest</span> <span class="p">{</span>

	<span class="k">protected</span> <span class="k">function</span> <span class="n">login</span><span class="p">(</span><span class="kt">WebGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
		<span class="c1">// ...</span>
	<span class="p">}</span>

	<span class="cd">/**
	 * @before login
	 */</span>
	<span class="k">function</span> <span class="n">banUser</span><span class="p">(</span><span class="kt">WebGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Logout'</span><span class="p">);</span>
		<span class="c1">// ...</span>
	<span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Just by using annotations you can control the invokations of methods of the Cest class. Sure, you should define your support methods with <code class="language-plaintext highlighter-rouge">protected</code>, so they won’t be executed as tests themselves. Another thing worth to mention, that callbacks defined in <code class="language-plaintext highlighter-rouge">after</code> annotation will be called even the main test has failed, thus it makes them useful for clean ups.</p>

<p>We still maintain and bugfix 1.6 branch and there will be 1.6 bugfix releases. The old release <code class="language-plaintext highlighter-rouge">1.6.9</code> (yep, 1.6.9 was released to with minor bugfixes) can be downloaded from <a href="https://codeception.com/releases/1.6.9/codecept.phar">https://codeception.com/releases/1.6.9/codecept.phar</a>.</p>

<h2 id="removed-dependencies">Removed Dependencies</h2>

<p>Optional dependencies were removed from the core, so if you use Composer version and one of the following packages:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="w">    </span><span class="nl">"behat/mink-selenium-driver"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.1.*"</span><span class="err">,</span><span class="w">
    </span><span class="nl">"facebook/php-sdk"</span><span class="p">:</span><span class="w"> </span><span class="s2">"3.*"</span><span class="err">,</span><span class="w">
    </span><span class="nl">"behat/mink-zombie-driver"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.1.*"</span><span class="err">,</span><span class="w">
    </span><span class="nl">"videlalvaro/php-amqplib"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span></code></pre></figure>

<p>you should include them manually in your <code class="language-plaintext highlighter-rouge">composer.json</code>. 
If you use phar version - nothing is changed for you.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.8</title>
      <link>https://codeception.com/10-07-2013/codeception-168.html</link>
      <pubDate>Mon, 07 Oct 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-07-2013/codeception-168</guid>
      <description><![CDATA[ <p>Yet another minor release before the 1.7 comes.</p>

<p>In 1.7 you will see new Selenium WebDriver module, better output formatter moved to Symfony Components, and other useful features. It will come shortly during next week(s). But for now lets list bugfixes contributed by our community members. Thank you all!</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>ZF2 module fixes by <strong>Marcelo Araújo</strong>.</li>
  <li>Cleanup for custom enum types in PostgreSQL module by <strong>korotovsky</strong>.</li>
  <li>Disabled fields are sent by <code class="language-plaintext highlighter-rouge">submitForm</code> method no more. Thx to <strong>TrustNik</strong>.</li>
  <li><code class="language-plaintext highlighter-rouge">seeResponseIsXml</code> added to REST module by <strong>FnTm</strong>. Expect more REST/Xml features in 1.7</li>
  <li>WebDriver module usage fixed.</li>
  <li>Fixed unit testing results display when used with CodeGuy object</li>
  <li><code class="language-plaintext highlighter-rouge">seeElement</code> and <code class="language-plaintext highlighter-rouge">dontSeeElement</code> work correctly now.</li>
  <li>Conditional Asserts work as expected now.</li>
  <li><code class="language-plaintext highlighter-rouge">seeCookie</code> can be used with different domain set. Thx <strong>vkn</strong>.</li>
  <li>fixed <code class="language-plaintext highlighter-rouge">submitForm</code> for forms that don’t have <code class="language-plaintext highlighter-rouge">submit</code> buttons in PhpBrowser by <strong>vkn</strong>.</li>
</ul>

<h2 id="translations">Translations</h2>

<p>It’s good for you to know, that Russian and Portuguese translations of Codeception Guides were started.
If you know either of this langueges (or even both, he-he) please, help us get translations done! By now several chapters are already translated, but you know, there are still lot of work,</p>

<ul>
  <li><a href="https://github.com/Codeception/codeception-guide-ru">Russian Guides</a>. Editor: <strong>xomaa</strong></li>
  <li><a href="https://github.com/Codeception/docs.pt_BR">Portuguese Guides</a>. Editor: <strong>Giuseppe</strong></li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>New Fashioned Classics: BDD Specs in PHPUnit</title>
      <link>https://codeception.com/10-04-2013/specification-phpunit.html</link>
      <pubDate>Fri, 04 Oct 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-04-2013/specification-phpunit</guid>
      <description><![CDATA[ <p>One of the most important requirements for tests is <strong>maintainability</strong>. 
The tests can live in a project for a months or even years. One day it may happen that some old tests start failing and the team got no idea about what the test does.</p>

<p>Does this test checks something important? Maybe specification has changed and the test should be rewritten?
The team who worked on tests that early days wrote them only to make them pass. Team is not sure what was the purpose of test.</p>

<p>In such situations it would have been nice if a developer who wrote the test at least has left some comments. But not. Usually no one documents tests. Test passes and developer is completely satisfied with that fact.</p>

<p>Proper test structure and readability is the only way to maintainable tests. <strong>Tests must not turn to a legacy code.</strong> Is there a way to write better tests?</p>

<p>The rule, dictated by BDD, is quite simple: write tests for specifications. Do not test just methods, test the behavior. As you know, there are plenty of BDD frameworks that replace classical unit testing with specification testing. You may have heard of <a href="https://rspec.info/">RSpec</a> in Ruby, <a href="https://pivotal.github.io/jasmine/">Jasmine</a>, <a href="https://visionmedia.github.io/mocha/">Mocha</a> <a href="https://jster.net/category/testing-frameworks#/bdd">and others</a> in JavaScript.</p>

<p>If you ever did testing in JavaScript you know how popular mentioned BDD frameworks are. Why can’t we have something similar in PHP? We got <a href="https://www.phpspec.net/">PHPSpec</a> which is nice, but looks much different from mentioned frameworks. What if we want something more usual? Something like <strong>Jasmine</strong> in PHP?</p>

<p>Even if we had such BDD framework none will ever adopt it as we have PHPUnit for all kind of testing in PHP. We won’t switch PHPUnit in favor of some geeky BDD tool. But actually to write BDD-styled tests, inspired by Jasmine we don’t need to do dramatic changes.</p>

<p>We can use <a href="https://github.com/Codeception/Specify">Specify</a>, a simple trait inserted into your PHPUnit’s TestCase that allows you to store several specifications in a test and write them in BDD way.</p>

<p>At first we will write down some specifications in a body of typical PHPUnit’s test:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// this is just a PHPUnit's testcase</span>
<span class="kd">class</span> <span class="nc">PostTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

	<span class="kn">use</span> <span class="nc">Codeception\Specify</span><span class="p">;</span>

	<span class="c1">// just a regular test declaration</span>
	<span class="k">public</span> <span class="k">function</span> <span class="n">testPublication</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post can be published'</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a title'</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a body'</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'author of post should not be banned'</span><span class="p">);</span>		
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Pretty sweet, we started with describing things before the test. But can’t we do the same with comments?
<code class="language-plaintext highlighter-rouge">specify</code> method is much better then comments as it introduces code blocks into PHPUnit.</p>

<p>To see it in action, let’s write the tests.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// this is just a PHPUnit's testcase</span>
<span class="kd">class</span> <span class="nc">PostTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

	<span class="kn">use</span> <span class="nc">Codeception\Specify</span><span class="p">;</span>

	<span class="c1">// just a regular test declaration</span>
	<span class="k">public</span> <span class="k">function</span> <span class="n">testPublication</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Post</span><span class="p">;</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setAuthor</span><span class="p">(</span><span class="k">new</span> <span class="nc">User</span><span class="p">());</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post can be published'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setTitle</span><span class="p">(</span><span class="s1">'Testing is Fun!'</span><span class="p">);</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setBody</span><span class="p">(</span><span class="s1">'Thats for sure'</span><span class="p">);</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a title'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertArrayHasKey</span><span class="p">(</span><span class="s1">'title'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">());</span>		
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a body'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertArrayHasKey</span><span class="p">(</span><span class="s1">'body'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">());</span>		
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'author of post should not be banned'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>			
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">getAuthor</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">setIsBanned</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>

			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setTitle</span><span class="p">(</span><span class="s1">'Testing is Fun!'</span><span class="p">);</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setBody</span><span class="p">(</span><span class="s1">'Thats for sure'</span><span class="p">);</span>			

			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertArrayHasKey</span><span class="p">(</span><span class="s1">'author'</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">());</span>
		<span class="p">});</span>		
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This code blocks will be executed inside the same test. But it’s important to notice that each code block is isolated, thus, when an assertion inside a block fails, the test won’t stop the execution. That is how the <code class="language-plaintext highlighter-rouge">specify</code> is different from comments.</p>

<p>Now we’ve got a list of specification and code examples for each case. If one day our site will allow micro-blogging, we can easily find <code class="language-plaintext highlighter-rouge">post should contain a body</code> specification and remove it. That’s pretty flexible, thus maintainable.</p>

<p>Please note, that all the specification are grouped by context. In plain PHPUnit you would create each code block as a separate method. This way it’s pretty hard to all the tests related to one specific feature, in our case - publishing.</p>

<p>Ok, we got nice specifications. But can we also replace classical asserts with some more BDD stuff? Sure. We have another tiny package <a href="https://github.com/Codeception/Verify">Verify</a> which is also inspired by Jasmine. <code class="language-plaintext highlighter-rouge">Assert</code> keyword is replaced either with <code class="language-plaintext highlighter-rouge">expect</code> (as Jasmine does) or <code class="language-plaintext highlighter-rouge">verify</code>. This asserts change the order of assertion to improve readability.</p>

<p>Let’s rewrite our test with <strong>Verify</strong> so you could feel the difference.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// this is just a PHPUnit's testcase</span>
<span class="kd">class</span> <span class="nc">PostTest</span> <span class="kd">extends</span> <span class="nc">PHPUnit_Framework_TestCase</span> <span class="p">{</span>

	<span class="kn">use</span> <span class="nc">Codeception\Specify</span><span class="p">;</span>

	<span class="c1">// just a regular test declaration</span>
	<span class="k">public</span> <span class="k">function</span> <span class="n">testPublication</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Post</span><span class="p">;</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setAuthor</span><span class="p">(</span><span class="k">new</span> <span class="nc">User</span><span class="p">());</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post can be published'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setTitle</span><span class="p">(</span><span class="s1">'Testing is Fun!'</span><span class="p">);</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setBody</span><span class="p">(</span><span class="s1">'Thats for sure'</span><span class="p">);</span>
			<span class="nf">expect_that</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a title'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nf">expect_not</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nf">expect</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">())</span><span class="o">-&gt;</span><span class="nf">hasKey</span><span class="p">(</span><span class="s1">'title'</span><span class="p">);</span>		
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'post should contain a body'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>
			<span class="nf">expect_not</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nf">expect</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">())</span><span class="o">-&gt;</span><span class="nf">hasKey</span><span class="p">(</span><span class="s1">'body'</span><span class="p">);</span>		
		<span class="p">});</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">specify</span><span class="p">(</span><span class="s1">'author of post should not be banned'</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="p">{</span>			
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">getAuthor</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">setIsBanned</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>

			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setTitle</span><span class="p">(</span><span class="s1">'Testing is Fun!'</span><span class="p">);</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">setBody</span><span class="p">(</span><span class="s1">'Thats for sure'</span><span class="p">);</span>			

			<span class="nf">expect_not</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">publish</span><span class="p">());</span>
			<span class="nf">expect</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">post</span><span class="o">-&gt;</span><span class="nf">errors</span><span class="p">())</span><span class="o">-&gt;</span><span class="nf">hasKey</span><span class="p">(</span><span class="s1">'author'</span><span class="p">);</span>
		<span class="p">});</span>		
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Basically it’s a deal of habit. The <code class="language-plaintext highlighter-rouge">expect(XX)-&gt;toBe(YY)</code> style is more natural for reading as you read from left to right. But If you got used to <code class="language-plaintext highlighter-rouge">assertXXX</code> syntax (where the code is read from right), you can skip <strong>Verify</strong> library.</p>

<hr />

<p>With just a few tiny libraries we converted a classical flat PHPUnit test into separate code blocks driven by specification. Test looks very similar to what we saw in Jasmine, just as we intended.</p>

<p>And the piece of advice to your team: introduce a rule “no assertion without specification” to make tests readable and easy to maintain.</p>

<p>You can install Specify and Verify via Composer:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php composer.phar require <span class="s2">"codeception/specify:*"</span> <span class="nt">--dev</span>
php composer.phar require <span class="s2">"codeception/verify:*"</span> <span class="nt">--dev</span></code></pre></figure>

<p>To introduce <code class="language-plaintext highlighter-rouge">specify</code> codeblocks, just add <code class="language-plaintext highlighter-rouge">use Codeception\Specify</code> into any TestCase file.
BDD styled assertions with <code class="language-plaintext highlighter-rouge">expect</code> keywords are installed automatically.</p>

<p><strong>Hint:</strong> Isolated codeblocks are especially useful <a href="https://github.com/Codeception/Specify#exceptions">for testing exceptions</a>.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.7</title>
      <link>https://codeception.com/09-14-2013/codeception-167.html</link>
      <pubDate>Sat, 14 Sep 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-14-2013/codeception-167</guid>
      <description><![CDATA[ <p>This release is minor, yet fixes lots of bugs you might have encountered. If you didn’t encounter them, well, then, lucky you. Still it’s a good idea to upgrade.</p>

<p>Here is the list of changes.</p>

<ul>
  <li><strong>fix to 80 port issue</strong>, if you had problems connecting to server via PhpBrowser, then this must be it. Thanks to <strong>@tiger-seo</strong>.</li>
  <li>fix in REST module when using <code class="language-plaintext highlighter-rouge">application/json</code> header and passing parameters.</li>
  <li><strong>seeJsonResponseContains</strong> of REST can now search on all nesting levels. Details below.</li>
  <li>fix to Sequence module.</li>
  <li>Step class code improved by <strong>guilhermeFranco</strong></li>
  <li>Using suite with defined namespace was improved by <strong>@Borales</strong>.</li>
  <li>Generators fixes by <strong>@piccagliani</strong> and <strong>davert</strong>.</li>
</ul>

<h2 id="rest-module-changes-example">Rest Module Changes Example</h2>

<p><em>added on 09/15/2013</em></p>

<p><code class="language-plaintext highlighter-rouge">seeJsonResponseContains</code> behavior is less strict now. Now you it checks for any inclusion of provided json in Response, and works for unordered arrays as well. Here is an example.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$response</span> <span class="o">=</span> <span class="s1">'{"ticket": {"title": "Bug should be fixed", "user": {"name": "Davert"}, "labels": null}}'</span><span class="p">;</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseContainsJson</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'ticket'</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">'title'</span> <span class="o">=&gt;</span> <span class="s1">'Bug should be fixed'</span><span class="p">)));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseContainsJson</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Davert'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseContainsJson</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'user'</span> <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Davert'</span><span class="p">)));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In previous versions, only the first assertion would pass. But now <code class="language-plaintext highlighter-rouge">seeJsonResponseContains</code> will scan for inclusion on all levels of response json.</p>

<p>There was no other way to get it tested unordered arrays. Until 1.6.7.
Here is a sample response:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
        </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Dalhousie Website"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://www.dal.ca"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"hashed_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ad920603a18be8a41207c0529200af45"</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w">
        </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Wikipedia - Brasil"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://pt.wikipedia.org/wiki/Brasil"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"hashed_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"01203b7a9a2a27c22bc828419d4b7dc9"</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">]</span></code></pre></figure>

<p>And test part that was failing in previous versions:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseContainsJson</span><span class="p">([</span><span class="s1">'url'</span> <span class="o">=&gt;</span>  <span class="s2">"https://pt.wikipedia.org/wiki/Brasil"</span><span class="p">]);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Example taken from <a href="https://github.com/Codeception/Codeception/issues/330">#330</a>
The case here, if you didn’t know the index of element, you couldn’t verify it with <code class="language-plaintext highlighter-rouge">seeJsonResponseContains</code>.
If you were using indexes, tests still should work for you.</p>

<p>Another change is checks for <code class="language-plaintext highlighter-rouge">null</code> values in response. Actually, we deserialized them in empty strings <code class="language-plaintext highlighter-rouge">""</code>, and this was a regular workaround to replace <code class="language-plaintext highlighter-rouge">null</code> with <code class="language-plaintext highlighter-rouge">""</code> in tests as proposed in <a href="https://github.com/Codeception/Codeception/issues/381">#381</a>. But if you did that, you should update your tests for 1.6.7, as <code class="language-plaintext highlighter-rouge">null</code> work as expected now.</p>

<p>So this is the changes that might affect your tests. If you got issues. <code class="language-plaintext highlighter-rouge">seeJsonResponseContains</code> has much more detailed output on fails, so it would be easier to find the cause and get it fixed.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Understanding AspectMock</title>
      <link>https://codeception.com/09-13-2013/understanding-aspectmock.html</link>
      <pubDate>Fri, 13 Sep 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-13-2013/understanding-aspectmock</guid>
      <description><![CDATA[ <p>As you may know, <a href="">AspectMock</a> is non-ordinary mocking framework that can override any method of any class in your application. This is practically useful If you want to unit test code, which was not aimed to be testable from start. Also AspectMock gives you power to write efficient code at first, and not affect production code with testing design.</p>

<h2 id="test-design">Test Design</h2>

<p>Even AspectMock proposes a flexibility in testing, it doesn’t drive you into bad application design.
If you use classes globally (without injecting them) or you use static properties, methods, or singletones, it’s all right while they are defined as your internal API. Such API methods should be well documented, especially for cases, where they should be used, and where not.</p>

<p>If we use ActiveRecord pattern, we can assume that all models are inherited from <code class="language-plaintext highlighter-rouge">ActiveRecord</code> class.
The only point in which our models is accessing database is <code class="language-plaintext highlighter-rouge">save</code> method of that class.
Thus, we need only to block its call, If we don’t want the database to be hit.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'ActiveRecord'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'save'</span> <span class="o">=&gt;</span> <span class="kc">false</span><span class="p">]);</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">User</span><span class="p">([</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">]);</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">save</span><span class="p">();</span> <span class="c1">// false</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Sure, integration testing using database gives us more reliable results. And no one ignores that fact. But unit tests allows to cover more cases, without implementing and loading fixtures. They are much faster too.</p>

<h2 id="features-and-drawbacks">Features and Drawbacks</h2>

<p>AspectMock may sounds cool for you, but you feel that there should be pitfalls. 
Let’s be honest, and list all of them here.</p>

<ul>
  <li>The most common issue is to get AspectMock installed. We won’t list different configuration options here, they are well documented in Github readme. But the idea is pretty simple: you should include directories with files expected to be mocked. If you don’t rely completely on autoloader from composer, you should include your autoloaders too.</li>
  <li>AspectMock will slow down execution in about 20%. That’s because all methods of all classes are intercepted.</li>
</ul>

<p>You may be curious <strong>If AspectMock affect the stack traces?</strong> The answer is <strong>no</strong>. AspectMock (starting from 0.4) does not change the line order in mocked classes, thus you get truth worthy information in stack trace. Sure, AspectMock changes those files, a bit, but more about that in next section.</p>

<p><strong>Can I debug my tests when using AspectMock?</strong> And here are the good news: <strong>Sure, you can!</strong> In Debug mode you will see your classes, with no mock including in them.</p>

<p>To summarize: AspectMock has no side effects on unit testing process. Its magic is properly hidden to not affect the development.</p>

<h2 id="dark-magic-inside">Dark Magic Inside</h2>

<p>Before implementing AspectMock into your project you might want to know, how it works in details.
AspectMock is powered by <a href="https://go.aopphp.com/">Go Aop Framework</a>.</p>

<p>Go AOP Framework uses <a href="https://php.net/manual/en/wrappers.php.php"><strong>php stream wrappers with filter</strong></a> to parse PHP files before requiring them. That may even happen in runtime.
Thus, by analyzing file, we can find all its methods, and inject mocking code into it. To do so, all <code class="language-plaintext highlighter-rouge">requires</code>should include a filter. This will look like:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">require</span> <span class="s1">'myfile.php'</span><span class="p">;</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>will be replaced with</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">require</span> <span class="s1">'php://read=go.source.transforming.loader/resource=myfile.php'</span><span class="p">;</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>That will make PHP file to be parsed before loading, and changed on the fly.
Go AOP is pretty smart to cache already parsed files.</p>

<p>Now time comes for AspectMock. For every method of every class, AspectMock inserts one line into very beginning of method definition. This sample class</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">User</span> <span class="p">{</span>
	
	<span class="k">function</span> <span class="n">setName</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
	<span class="p">}</span>	

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>will be replaced with:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">User</span> <span class="p">{</span>
	
	<span class="k">function</span> <span class="n">setName</span><span class="p">(</span><span class="nv">$name</span><span class="p">)</span>
	<span class="p">{</span> <span class="k">if</span> <span class="p">((</span><span class="nv">$__am_res</span> <span class="o">=</span> <span class="nf">__amock_before</span><span class="p">(</span><span class="nv">$this</span><span class="p">,</span> <span class="k">__CLASS__</span><span class="p">,</span> <span class="k">__FUNCTION__</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="nv">$name</span><span class="p">),</span> <span class="kc">false</span><span class="p">))</span> <span class="o">!==</span> <span class="nb">__AM_CONTINUE__</span><span class="p">)</span> <span class="k">return</span> <span class="nv">$__am_res</span><span class="p">;</span> 
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="nv">$name</span><span class="p">;</span>
	<span class="p">}</span>	

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see only one line is added. If a stub was registered for this method, its result will be returned, and method itself won’t be invoked.</p>

<p>If you will enter into class in debug mode, you won’t see the line injected by AspectMock. But you will notice its there, even not show, in step by step debug.</p>

<p>And that’s probably all the dark magic you should be aware of. Probably it’s not too tricky and you will get along with it.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Unit tests are important part of testing pyramid. They are fast and they are flexible. You should not ignore them just because it may be hard for you to implement them. Its not that hard anymore. With AspectMock you can get a good code coverage with less efforts for any kind of modern php application.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.6: Sequences</title>
      <link>https://codeception.com/08-29-2013/codeception-sequences-new-webdriver.html</link>
      <pubDate>Thu, 29 Aug 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-29-2013/codeception-sequences-new-webdriver</guid>
      <description><![CDATA[ <p>A minor release with one major announcement. In <code class="language-plaintext highlighter-rouge">1.6.6</code> most bugfixes were included from pull requests. Thanks for everyone who did the contributions.</p>

<h2 id="sequence">Sequence</h2>

<p>Also a very tiny new module was included. It’s <a href="/docs/modules/Sequence">Sequence</a> which was created to generate unique data for your tests. Sequnces become pretty handy if you don’t do database cleanup before each tests. They guarantee you can get unique names and values for each test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy\PostSteps</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create a post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">createPost</span><span class="p">(</span><span class="s1">'Post'</span><span class="mf">.</span><span class="nf">sq</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="s1">'Lorem Ipsum'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post created sucessfully'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post'</span><span class="mf">.</span><span class="nf">sq</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="s1">'#posts'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>No matter how much times you execute this test, each time you see a new post is created with different name.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>Remote codecoverage now works with Selenium2 module. <strong>Please <a href="https://github.com/Codeception/c3/raw/master/c3.php">update c3.php file</a> to use it</strong>.</li>
  <li>IoC container access in <strong>Laravel4</strong> module by <strong>@allmyitjason</strong>.</li>
  <li>PostgreSQL driver fixes by <strong>@mohangk</strong> and **@korotovsky **.</li>
  <li>don’t rollback for inactive transaction in Dbh module by <strong>@sillylogger</strong></li>
  <li>fix to guy classes generation with namespaces by <strong>@vinu</strong>.</li>
  <li>SQLite improvements by <strong>@piccagliani</strong></li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<hr />

<h2 id="living-on-the-edge-webdriver">Living on the Edge: WebDriver</h2>

<p>In July a group of Facebook developers set the goal to write the complete new Selenium Webdriver bindings. 
They decided to do it finally the right way, with the same WebDriver interface it is used in other languages like Java and C#. Ironically, Selenium2 module of Codeception uses the old webdriver bindings from Facebook.They were very hard in use, and had lots of issues. Most common issues were solved in <a href="https://github.com/Element-34/php-webdriver">Element34</a> fork, which was then forked by <a href="https://github.com/instaclick/php-webdriver">Instaclick</a> to bring namespaces and PSR-0, which was then <a href="https://github.com/Behat/MinkSelenium2Driver">used in Mink’s Selenium2Driver</a>, and Mink was used in Codeception.</p>

<p>Pretty tricky, right?</p>

<p>Currently there are 3 WebDriver bindings in PHP.</p>

<ul>
  <li><a href="https://phpunit.de/manual/current/en/selenium.html#selenium.selenium2testcase">Selenium2TestCase of PHPUnit</a> which is the most old, the most complete and the most OOP webdriver implementation. But if you have worked with its api, you understand how robust it is to learn and use.</li>
  <li><a href="https://github.com/Element-34/php-webdriver">Element34 fork</a> based on initial facebook/webdriver bindings, but with hooks to solve common pitfalls.</li>
  <li><a href="https://github.com/Behat/MinkSelenium2Driver">Selenium2Driver</a> of Mink which incorporates Element34 bindings and <em>Syn.js</em> library to perform most of interactions via JavaScript bypassing WebDriver API.</li>
</ul>

<p>Ok. Now we have new <a href="https://github.com/facebook/php-webdriver">facebook webdriver bindings</a>. They are in active development and they lack proper documentation. But the good part of it, that even without documentation you will easily learn how to work with them. Any question on StackOverflow with examples in Java or C# will work in PHP just the same way.</p>

<p>In Codeception <code class="language-plaintext highlighter-rouge">master</code> we created a new <a href="https://github.com/Codeception/Codeception/blob/master/docs/modules/WebDriver.md"><strong>WebDriver</strong></a> module which uses new webdriver bindings.
This module will be included into first 1.7 release, but it won’t be recommended for regular use before the stable version of php-webdriver is released.</p>

<p>To try the new WebDriver you should switch to <code class="language-plaintext highlighter-rouge">dev-master</code> in <code class="language-plaintext highlighter-rouge">composer.json</code> or use the pre-prelease <a href="https://github.com/Codeception/Codeception/blob/master/package/codecept.phar">phar package</a>.</p>

<p>WebDriver module does not implement everyhting the Selenium2 module has. There is no right clicks, drag and drops, and more. But there are few handy improvements:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">submitForm</code> action as in PhpBrowser.</li>
  <li><code class="language-plaintext highlighter-rouge">waitForElement</code> action to wait for element to appear on page.</li>
  <li><code class="language-plaintext highlighter-rouge">selectOption</code> and <code class="language-plaintext highlighter-rouge">checkOption</code> now both work with radio buttons.</li>
  <li><code class="language-plaintext highlighter-rouge">seeElementInDOM</code> to check the invisible elements.</li>
  <li><code class="language-plaintext highlighter-rouge">waitForElementChange</code> to wait that element changed</li>
  <li><a href="https://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits">implicit waits</a> with <code class="language-plaintext highlighter-rouge">wait</code> config prameter (default is 5 secs).</li>
  <li><code class="language-plaintext highlighter-rouge">maximizeWindow</code> specially for <strong>@aditya-</strong> :).</li>
</ul>

<p>In all other ways its pretty compatible with Selenium2 module. Try it on your own risk or wait for stable versions.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.5: Debug and Bugfixes</title>
      <link>https://codeception.com/08-09-2013/codeception-1-6-5-minor.html</link>
      <pubDate>Fri, 09 Aug 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-09-2013/codeception-1-6-5-minor</guid>
      <description><![CDATA[ <p>This is a minor release, mostly done to fix some bugs, you have encountered.
Please, submit your Pull Requests for the bugs critical of yours. Most of pull requests are accepted, but if you will start a proposal, we can recommend you the best way to implement the fix.</p>

<h2 id="selenium2-compatiblity">Selenium2 Compatiblity</h2>

<p>Selenium2 server v.2.34 was released recently and to use it you need to update Codeception.
If you use phar version, you should replace your old <code class="language-plaintext highlighter-rouge">codecept.phar</code> with new one.</p>

<h2 id="debug-levels">Debug Levels</h2>

<p>At least one useful feature we prepared for you. Debug output in <code class="language-plaintext highlighter-rouge">PhpBrowser</code> and <code class="language-plaintext highlighter-rouge">REST</code> modules was extended with additional information that will be printed in <code class="language-plaintext highlighter-rouge">debug</code> mode:</p>

<p><img src="/images/debug.png" alt="debug" /></p>

<p>Tests would be much easier to debug when you see reponse headers, status codes and client cookies.
Don’t forget to add <code class="language-plaintext highlighter-rouge">--debug</code> to run your PhpBrowser acceptance tests, option to see that.</p>

<h2 id="title-actions">Title Actions</h2>

<p>Two basic yet useful actions were added to all web interaction modules.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInTitle</span><span class="p">(</span><span class="s1">'My Blog | My Post #1'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">dontSeeInTitle</span><span class="p">(</span><span class="s1">'Her Blog'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Should be useful, right?</p>

<h2 id="single-test">Single Test</h2>

<p>Finally you can now execute a single test from <code class="language-plaintext highlighter-rouge">Cest</code> or <code class="language-plaintext highlighter-rouge">Test</code> testcases.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar run tests/unit/UserModelTest.php:testSave</code></pre></figure>

<p>In this case we will execute only <code class="language-plaintext highlighter-rouge">testSave</code> test out of <code class="language-plaintext highlighter-rouge">UserModelTest</code> TestCase.
The same works for Cests. You may write only the beginning of test name, to execute it.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>fix to correct displaying of non-latin characters in html-report by <strong>shofel</strong></li>
  <li><code class="language-plaintext highlighter-rouge">--xml</code> output for Codeception\TestCase\Test fixed</li>
  <li>fixed <code class="language-plaintext highlighter-rouge">unserialize</code> error during code coverage. Anyway, if you ever seen this, you didn’t setup coverage correctly.</li>
  <li>Interactive console <code class="language-plaintext highlighter-rouge">console</code> command does not boot with error stacktrace.</li>
  <li>Clearing only tables and not views in Db-&gt;cleanup()</li>
  <li>PDO <code class="language-plaintext highlighter-rouge">$dbh</code> is now passed to Db module corretcly #414</li>
</ul>

<h2 id="release-plan">Release Plan</h2>

<p>Also we are planning to get more stable releases, and follow the Semantic Versioning. 
This means that current stable branch is 1.6. If you submit patches and bugfixes, you should propose them into <code class="language-plaintext highlighter-rouge">1.6</code> branch. Experimental features should go to master.</p>

<table>
  <thead>
    <tr>
      <th>release</th>
      <th>branch</th>
      <th>status</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Stable</strong></td>
      <td><strong>1.6</strong></td>
      <td><a href="https://travis-ci.org/Codeception/Codeception"><img src="https://secure.travis-ci.org/Codeception/Codeception.png?branch=1.6" alt="Build Status" /></a> <a href="https://packagist.org/packages/Codeception/Codeception"><img src="https://poser.pugx.org/Codeception/Codeception/version.png" alt="Latest Stable" /></a></td>
    </tr>
    <tr>
      <td><strong>Development</strong></td>
      <td><strong>master</strong></td>
      <td><a href="https://travis-ci.org/Codeception/Codeception"><img src="https://secure.travis-ci.org/Codeception/Codeception.png?branch=master" alt="Build Status" /></a> <a href="https://depending.in/Codeception/Codeception"><img src="https://d2xishtp1ojlk0.cloudfront.net/d/2880469" alt="Dependencies Status" /></a></td>
    </tr>
  </tbody>
</table>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Testing WordPress Plugins with Codeception. Part 2</title>
      <link>https://codeception.com/08-01-2013/testing-wordpress-plugins-2.html</link>
      <pubDate>Thu, 01 Aug 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-01-2013/testing-wordpress-plugins-2</guid>
      <description><![CDATA[ <p>In <a href="https://codeception.com/07-24-2013/testing-wordpress-plugins.html">previous part of this tutorial</a> we installed Codeception and got a simple test for <a href="https://wordpress.org/plugins/user-submitted-posts/">User Submitted Posts</a> plugin. We tested that user can send a post and see a message that the post was successfully sent. Nothing more.</p>

<p>Let’s remind the test <code class="language-plaintext highlighter-rouge">SubmitPostCept</code> we done previously:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'select[name=user-submitted-category]'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Success! Thank you for your submission.'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>But well, we didn’t verify that the admin has received this post. And it can be published after a moderation.
Thus, we will require few more steps to make a test complete. We will need to login to WordPress admin dashboard.</p>

<p><img src="/images/wordpress/wp2_dashboard.png" alt="Dashboard" /></p>

<p>Test commands which allow us to do that are pretty obvious. To keep the code listing shorter we won’t show the code from previous lesson. But you should understand that we just append new commands to the previous steps.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Then we go to <strong>Posts</strong> section to get all the post listed. We expect to see the “Game of Drones” post in the list.</p>

<p><img src="/images/wordpress/wp2_posts.png" alt="Posts" /></p>

<p>Let’s also check that it was not published by default and it is in <code class="language-plaintext highlighter-rouge">Pending</code> state. <code class="language-plaintext highlighter-rouge">Game of Drones Review - Pending</code> should be found inside the <code class="language-plaintext highlighter-rouge">table</code> html tag, right? We can even specify the CSS class <code class="language-plaintext highlighter-rouge">.posts</code> for that table.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>That’s right, the <code class="language-plaintext highlighter-rouge">see</code> command we use for assertions (and the test will fail if assertions fail) has a second parameter which allow us to narrow the results from the whole page, to a particular area on a page, which we can define by CSS:</p>

<p><img src="/images/wordpress/wp2_posts_table_css.png" alt="Posts CSS" /></p>

<p>What’s left? We need to review and publish this post, right?
The result we expect… Well, we will trust the notifications once again, and message <strong>Post published</strong> should be enough for us.</p>

<p><img src="/images/wordpress/wp2_published.png" alt="Published" /></p>

<p>And that’s how we will do that in test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Publish'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post published'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And that would be a good point to execute tests once again. Probably you remember, that you need execute <code class="language-plaintext highlighter-rouge">codecept.phar</code> with <code class="language-plaintext highlighter-rouge">run</code> parameter from console.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar run</code></pre></figure>

<p>What we are seeing now? Oh no. Just another fail.</p>

<p><img src="/images/wordpress/wp2_fail.png" alt="Fail" /></p>

<p>What could go wrong? Hopefully Codeception gives us a suggestion to look for the complete HTML code in <code class="language-plaintext highlighter-rouge">_log</code> directory. This directory, actually  <code class="language-plaintext highlighter-rouge">tests/_log</code>, was meant to store all data related to test execution. We can see there two log files, and the file which we actually need: <code class="language-plaintext highlighter-rouge">SubmitPostCept.php.page.fail.html</code>.</p>

<p><img src="/images/wordpress/wp2_log.png" alt="Log" /></p>

<p>This file, named after our test name, stores the HTML that was on page, before the fail. Let’s open it in a browser to get a clue what might go wrong here.</p>

<p><img src="/images/wordpress/wp2_publish.png" alt="Publish" /></p>

<p>It looks like we are still on the <strong>Edit Post</strong> page we were before. And the post status is still <code class="language-plaintext highlighter-rouge">Pending Review</code>. It looks like <code class="language-plaintext highlighter-rouge">click('Publish')</code> command didn’t do its job.</p>

<p>Take a look on screenshot. as you can see, word <em>Publish</em> occur several times on a page. We can assume that we were clicking wrong one. What should we do in this case? We can specify the exact that blue <em>Publish</em> button with CSS.</p>

<p>Codeception can use CSS instead of names for clicking the elements. The button have <code class="language-plaintext highlighter-rouge">id=publish</code> attribute, thus, it can be found by <code class="language-plaintext highlighter-rouge">#publish</code> selector. That what we would probably do if we were using jQuery.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Edit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#publish'</span><span class="p">);</span> <span class="c1">// id of "Publish" button</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post published'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And that fixes the test. You can check that by executing test once again. Let’s not trust the notification test and check that a post really is on site. We can click <code class="language-plaintext highlighter-rouge">View Post</code> link right near the <code class="language-plaintext highlighter-rouge">Post updated</code> message.</p>

<p><img src="/images/wordpress/wp2_page.png" alt="Page" /></p>

<p>What we will check that there is site motto on a page (thus we know, we see the blog theme),
and that post title is shown in <code class="language-plaintext highlighter-rouge">.entry-title</code> class. And yep, we see this story is “epic and amazing”.
Let’s face the final and complete code of our test:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'select[name=user-submitted-category]'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Success! Thank you for your submission.'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Edit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#publish'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post published'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'View Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Just another WordPress site'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'.entry-title'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Well, we did a good job. But the test is like too long. And we can’t understand what was going on here.
We can add comments to the code, and Codeception has some valuable helpers to add extra text informations with <code class="language-plaintext highlighter-rouge">expect</code> and <code class="language-plaintext highlighter-rouge">amGoingTo</code> commands.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'submit a post as a regular user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'select[name=user-submitted-category]'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Success! Thank you for your submission.'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'log in as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/wp-login.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Dashboard'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'submitted post was added to a list'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'table.posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'publish this post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Edit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#publish'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Post published'</span><span class="p">);</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'post is available on blog'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'View Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Just another WordPress site'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Game of Drones Review'</span><span class="p">,</span><span class="s1">'.entry-title'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>We divided our test scenario into logical parts. At least we have left some notice about what is going on and what we were going to achieve. If we execute test with <code class="language-plaintext highlighter-rouge">--steps</code> option, we will get a output with all passed steps listed:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar run <span class="nt">--steps</span></code></pre></figure>

<p><img src="/images/wordpress/wp2_final.png" alt="Final" /></p>

<p>Our comments were added to list of passed steps, thus we can easily understand what was going on.
And that’s quite enough for today. Our test is pretty mature, and covers not only plugin functionality, but WordPress core functions too. Whenever this plugin gets updated, this test should pass to ensure we did everything right.</p>

<p>But the only thing left. After we executed tests several times, we got this picture on <code class="language-plaintext highlighter-rouge">Posts</code> screen.</p>

<p><img src="/images/wordpress/wp2_trash.png" alt="Previous Posts" /></p>

<p>We have attack of clones here. Yep, each test created its own post and published it. Probably, it is not a good idea to pollute the blog with dozens of posts with similar names. We use post title and content in a test, so probably we can’t be sure, what post we are dealing with: current one or the post from a previous test.</p>

<p>That will lead us to the idea of <strong>data cleanup</strong>. Probably we should delete post after it was published, to revert all our changes. Alternatively we can install <a href="https://wordpress.org/plugins/wordpress-reset/">WordPress Reset Plugin</a> to reset WordPress to its initial state. In both cases we will need to append some steps to our test to get data cleaned before the next test.</p>

<hr />

<p>Let’s make this your home task. To not start with scratch, you can <a href="https://github.com/Codeception/WordPress-plugin-testing/archive/lesson-2.zip"><strong>download code of this tutorial</strong></a> or clone it on <a href="https://github.com/Codeception/WordPress-plugin-testing/tree/lesson-2">Github</a>.</p>

<p>In next lesson we will try to refactor this test and get a few more of them. Don’t worry, they will be much shorter than this one. See you soon!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Nothing is Untestable: AspectMock in Action</title>
      <link>https://codeception.com/07-31-2013/nothing-is-untestable-aspect-mock.html</link>
      <pubDate>Wed, 31 Jul 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-31-2013/nothing-is-untestable-aspect-mock</guid>
      <description><![CDATA[ <blockquote>
  <p>“Nothing is True, Everything is Permitted” 
<em>William S. Burroughs</em></p>
</blockquote>

<p>We already announced <a href="https://github.com/Codeception/AspectMock">AspectMock</a>, the mocking framework that may dramatically change the way you do testing in PHP. <a href="https://jeffrey-way.com/blog/2013/07/24/aspectmock-is-pretty-neat/">In this video this Jeffrey Way</a> shows how AspectMock is different from others. In this post we will demonstrate its powers too, and we will try to break some stereotypes about PHP testing.</p>

<p>To get the code tested, you should always keep in mind how you would write a test for it. 
We know unit testing requires some good practices to follow and bad practices to avoid.</p>

<p>For example, you should not use singletons. They are bad. Why? Code that use singletons can’t be tested.</p>

<p>But what if we could mock singletons:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">function</span> <span class="n">testSingleton</span><span class="p">()</span>
<span class="p">{</span>
	<span class="nv">$class</span> <span class="o">=</span> <span class="nc">MySingleton</span><span class="o">::</span><span class="nf">getInstance</span><span class="p">();</span>
	<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertInstanceOf</span><span class="p">(</span><span class="s1">'MySingleton'</span><span class="p">,</span> <span class="nv">$class</span><span class="p">);</span>
	<span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'MySingleton'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'getInstance'</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nc">DOMDocument</span><span class="p">]);</span>
	<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertInstanceOf</span><span class="p">(</span><span class="s1">'DOMDocument'</span><span class="p">,</span> <span class="nv">$class</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And with AspectMock we really do it - the test is passing.
Then should we still consider a singleton to be a bad practice?</p>

<h2 id="beyond-good-and-evil">Beyond Good and Evil</h2>

<p>Classes and methods in PHP are declared statically and can’t be changed in runtime.
This can be treated as language limitation. 
Dependency Injection pattern can be used as a workaround for this limitation and widely used for testing.
AspectMock breaks the limitation. The same can probably be achieved with Runkit extension. But AspectMock doesn’t require you to install additional extensions, and uses only PHP methods to do its job.</p>

<p>“Testability” should not be used as argument deciding what design pattern is right to use and what is not.
When you develop with PHP you should always rely on common sense only. Production code should be efficient, fast, readable, and maintainable. The tests should not introduce redundant abstractions to the production code.</p>

<h3 id="real-world-experience-with-yii2">Real World Experience With Yii2</h3>

<p>Let’s get hands on AspectMock. We will use a demo application from the upcoming <a href="https://github.com/yiisoft/yii2">Yii2 framework</a>.
Despite having dependency injection container, Yii2 does not use it for models. It relies on static calls to global <code class="language-plaintext highlighter-rouge">Yii</code> class.</p>

<p>Take a look into <code class="language-plaintext highlighter-rouge">LoginForm</code> model of <code class="language-plaintext highlighter-rouge">advanced</code> application from the Yii2 repo.</p>

<p>Here is the source code:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">common\models</span><span class="p">;</span>

<span class="kn">use</span> <span class="nc">Yii</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">yii\base\Model</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">LoginForm</span> <span class="kd">extends</span> <span class="nc">Model</span>
<span class="p">{</span>
	<span class="k">public</span> <span class="nv">$username</span><span class="p">;</span>
	<span class="k">public</span> <span class="nv">$password</span><span class="p">;</span>
	<span class="k">public</span> <span class="nv">$rememberMe</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">rules</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">return</span> <span class="k">array</span><span class="p">(</span>
			<span class="c1">// username and password are both required</span>
			<span class="k">array</span><span class="p">(</span><span class="s1">'username, password'</span><span class="p">,</span> <span class="s1">'required'</span><span class="p">),</span>
			<span class="c1">// password is validated by validatePassword()</span>
			<span class="k">array</span><span class="p">(</span><span class="s1">'password'</span><span class="p">,</span> <span class="s1">'validatePassword'</span><span class="p">),</span>
			<span class="c1">// rememberMe must be a boolean value</span>
			<span class="k">array</span><span class="p">(</span><span class="s1">'rememberMe'</span><span class="p">,</span> <span class="s1">'boolean'</span><span class="p">),</span>
		<span class="p">);</span>
	<span class="p">}</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">validatePassword</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">findByUsername</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">username</span><span class="p">);</span>
		<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$user</span> <span class="o">||</span> <span class="o">!</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">validatePassword</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">password</span><span class="p">))</span> <span class="p">{</span>
			<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">addError</span><span class="p">(</span><span class="s1">'password'</span><span class="p">,</span> <span class="s1">'Incorrect username or password.'</span><span class="p">);</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">login</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">validate</span><span class="p">())</span> <span class="p">{</span>
			<span class="nv">$user</span> <span class="o">=</span> <span class="nc">User</span><span class="o">::</span><span class="nf">findByUsername</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">username</span><span class="p">);</span>
			<span class="nc">Yii</span><span class="o">::</span><span class="nv">$app</span><span class="o">-&gt;</span><span class="n">user</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">rememberMe</span> <span class="o">?</span> <span class="mi">3600</span><span class="o">*</span><span class="mi">24</span><span class="o">*</span><span class="mi">30</span> <span class="o">:</span> <span class="mi">0</span><span class="p">);</span>
			<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see, it can’t be tested in classical unit testing. The only option we have here is to write an integration test for this class. 
But with AspectMock we can easily get this class tested with 100% code coverage.</p>

<p>Let’s test successful and unsuccessful login scenarios in <code class="language-plaintext highlighter-rouge">LoginForm</code>.</p>

<p>LoginForm relies on User class. That’s why to write a test, we will mock some of its methods.
We will create a mock with <code class="language-plaintext highlighter-rouge">test::double</code> call. In a second argument we are passing the methods that are goint to be replaced and the values they should return.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">setUp</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'common\models\User'</span><span class="p">,</span> <span class="p">[</span>
            <span class="s1">'findByUsername'</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nc">User</span><span class="p">,</span>
            <span class="s1">'getId'</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
        <span class="p">]);</span>

    <span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>With this <code class="language-plaintext highlighter-rouge">User::findByUsername()</code> will always return an empty <code class="language-plaintext highlighter-rouge">User</code> instance.
And user id will always be 1. For user to log in we need that <code class="language-plaintext highlighter-rouge">$user-&gt;validatePassword()</code> returned true.
We will mock that call in a test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testCanLoginWhenValid</span><span class="p">()</span>
<span class="p">{</span>
    <span class="nv">$user</span> <span class="o">=</span> <span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'common\models\User'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'validatePassword'</span> <span class="o">=&gt;</span> <span class="kc">true</span><span class="p">]);</span>

    <span class="nv">$model</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LoginForm</span><span class="p">();</span>
    <span class="nv">$model</span><span class="o">-&gt;</span><span class="n">username</span> <span class="o">=</span> <span class="s1">'davert'</span><span class="p">;</span>
    <span class="nv">$model</span><span class="o">-&gt;</span><span class="n">password</span> <span class="o">=</span> <span class="s1">'123456'</span><span class="p">;</span>

    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$model</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">());</span>
    <span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">verifyInvoked</span><span class="p">(</span><span class="s1">'findByUsername'</span><span class="p">,[</span><span class="s1">'davert'</span><span class="p">]);</span>
    <span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">verifyInvoked</span><span class="p">(</span><span class="s1">'validatePassword'</span><span class="p">,[</span><span class="s1">'123456'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>Additionally we did a check that <code class="language-plaintext highlighter-rouge">validatePassword</code> method was called, and user was found by <code class="language-plaintext highlighter-rouge">findByUsername</code> call.
In production environment, this methods would use the database.</p>

<p>The same way we can check that user can’t log in with invalid password:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testCantLoginWhenInvalid</span><span class="p">()</span>
<span class="p">{</span>
	<span class="nv">$user</span> <span class="o">=</span> <span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'common\models\User'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'validatePassword'</span> <span class="o">=&gt;</span> <span class="kc">false</span><span class="p">]);</span>

	<span class="nv">$model</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LoginForm</span><span class="p">();</span>
	<span class="nv">$model</span><span class="o">-&gt;</span><span class="n">username</span> <span class="o">=</span> <span class="s1">'davert'</span><span class="p">;</span>
	<span class="nv">$model</span><span class="o">-&gt;</span><span class="n">password</span> <span class="o">=</span> <span class="s1">'123456'</span><span class="p">;</span>

	<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$model</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">());</span>
	<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">verifyInvoked</span><span class="p">(</span><span class="s1">'findByUsername'</span><span class="p">,[</span><span class="s1">'davert'</span><span class="p">]);</span>
	<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">verifyInvoked</span><span class="p">(</span><span class="s1">'validatePassword'</span><span class="p">,[</span><span class="s1">'123456'</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>And in the end we will also check that user can’t be logged in without a password.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">testCantLoginWithoutPassword</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">test</span><span class="o">::</span><span class="nf">double</span><span class="p">(</span><span class="s1">'common\models\User'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'validatePassword'</span> <span class="o">=&gt;</span> <span class="kc">true</span><span class="p">]);</span>
    <span class="nv">$model</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">LoginForm</span><span class="p">();</span>
    <span class="nv">$model</span><span class="o">-&gt;</span><span class="n">username</span> <span class="o">=</span> <span class="s1">'davert'</span><span class="p">;</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$model</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">());</span>
    <span class="nv">$model</span><span class="o">-&gt;</span><span class="n">password</span> <span class="o">=</span> <span class="s1">'123456'</span><span class="p">;</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$model</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">());</span>
<span class="p">}</span>    
<span class="cp">?&gt;</span></code></pre></figure>

<p>If we execute this tests with Codeception we will see all them pass successfully:</p>

<p><img src="/images/aspect_mock_ok.png" alt="passed" /></p>

<p>If you want to see this with your own eyes, <a href="https://github.com/DavertMik/Yii2-AspectMock">clone this application from Github</a> and run Codeception tests:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php vendor/bin/codecept run</code></pre></figure>

<p>Pay attention to <code class="language-plaintext highlighter-rouge">tests/_bootstrap.php</code> file where AspectMock Kernel is initialized. Yii autoloader was loaded through AspectKernel as well.
That is important to point AspectMock to a custom autoloader if you do not rely on Composer’s autoloader entirely.</p>

<h2 id="how-it-works">How it Works</h2>

<p>There are no magical meadows and mighty unicorns in a hat. Still AspectMock uses something really powerful to break the rules.
You may have heard of <a href="https://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect Oriented Programming</a>. <a href="https://github.com/lisachenko/go-aop-php">Go AOP framework</a>, developed by <strong>@lisachenko</strong> does awesome job to bring the AOP to PHP world. It intercepts all method calls and allows to put your own advices for them. The AspectMock is just an advice on top of Go Aop.</p>

<p>Go Aop scnans all libraries and enhances <code class="language-plaintext highlighter-rouge">include</code> and <code class="language-plaintext highlighter-rouge">require</code> statements with PHP filters. 
Go adds a parent proxy class to any loaded PHP class on the fly. So If we get back to Yii2 example, <code class="language-plaintext highlighter-rouge">User::findByUsername</code> call will invoke that method on a proxy class.</p>

<h2 id="conclusions">Conclusions</h2>

<p><strong>AspectMock still considered to be an experimental project.</strong>
But it has a wide potential. It is very simple and easy to use. It has very tiny api easy to remember and understand. 
That’s why tests developed with AspectMock are very clean and readable.</p>

<p><strong>AspectMock is not a testing tool for the bad code.</strong> The good code is efficient code. WordPress is much popular then any PHP framework, because of its efficiency. Magento does not have unit tests (only integration), but is the most popular ecommerce platform. We can’t say how many there are unit tests in Facebook, but we can bet, it started without unit tests. Code should do its job. Code should be readable and maintanable. Overusing dependency injection does not make the code more efficient in any sense. By the way, <a href="https://david.heinemeierhansson.com/2012/dependency-injection-is-not-a-virtue.html">in Ruby dependency injection is not widely used</a>, but as you may know ruby developers are very passionate about testing.</p>

<p><strong>AspectMock is not a tool for newbies</strong> who just didn’t manage to learn the good practices.
It is advanced tool, that require you to set dependencies explicitly in a test. That may require deep knowledge on internals of framework you use.</p>

<p>You can try it on your own project. If you have code parts that can’t be unit tested in classical manner, then AspectMock can do a job for you.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Testing WordPress Plugins with Codeception. Part 1</title>
      <link>https://codeception.com/07-24-2013/testing-wordpress-plugins.html</link>
      <pubDate>Wed, 24 Jul 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-24-2013/testing-wordpress-plugins</guid>
      <description><![CDATA[ <p>WordPress has dozens of plugins. And probably you have developed your own.
How would you know your plugin works for everyone? Does it conflicts with others?
Does it work after your last change?</p>

<p>Oh yes, releasing the plugin means to make it reliable. This why we highly recommend to use automated testing in your development. Its not that really hard as you expect. Quite the contrary: automated testing saves your time for clicking and filling forms on a page.</p>

<p>In this post we will examine how can you test a sample WordPress plugin with Codeception framework. Our patient is <a href="https://wordpress.org/plugins/user-submitted-posts/">User Submitted Posts</a> plugin by Jeffrey Starr.</p>

<p>This plugin allows regular users to submit a posts to your WordPress blog.</p>

<p>We assume a plugin is already installed and activated.</p>

<p><img src="/images/wordpress/Plugins.png" alt="Plugins Activated" /></p>

<p>And we created <em>“Submit a Post”</em> page with a plugin snippet <code class="language-plaintext highlighter-rouge">[user-submitted-posts]</code> included. Through this page we expect user stories to be submitted.</p>

<p><img src="/images/wordpress/SubmitPost.png" alt="Submit Post" /></p>

<p>This plugin has lots of settings that include post fields, available categories, security issues, etc. What we want to do is try to switch different options and try to submit a post. Depending on option switched we will see some changes in the form, moderation or publishing process.</p>

<h3 id="wordpress-setup">WordPress Setup</h3>

<p>To begin write a test we will need to do some preperations.
Our test won’t pass, if the page contains captcha: dummy web crawler has no idea how to solve it.
Thus, we will disable captcha field in Submit Post form by editing plugin’s options.</p>

<p>We will use category <strong>Game of Drones</strong> in our tests. Our goal is to verify that user is can to submit a post to into it. Lets enable it in plugin options:</p>

<p><img src="/images/wordpress/WP_Settings.png" alt="Settings" /></p>

<p>If you are lazy to do all the setup by hands, you can <a href="https://raw.github.com/Codeception/WordPress-plugin-testing/master/setup.sh">execute this setup script</a> on a freshly installed WordPress.</p>

<p>Automation of testing allows us to write a script one time and replay it whenever a change is introduced. Will the plugin work when WordPress hits new release? Will the plugin work when we introduce a new option? Without automated testing we would spend hours to check the same stuff over and over. Lets spend a few hours writing a proper tests, and save days on manual testing.</p>

<h3 id="install-codeception">Install Codeception</h3>

<p>Codeception can be easily installed. It requires <strong>PHP 5.3</strong> and higher. You can <a href="https://codeception.com/thanks">download it here</a> or grab from site with <code class="language-plaintext highlighter-rouge">wget</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar</code></pre></figure>

<p>Downloaded <code class="language-plaintext highlighter-rouge">codecept.phar</code> file should be placed into your WordPress directory.
This file should be executed with PHP from console</p>

<p><img src="/images/wordpress/Console.png" alt="Console" /></p>

<p>To install it run the <code class="language-plaintext highlighter-rouge">bootstrap</code> command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar bootstrap</code></pre></figure>

<p>This creates a new directory <code class="language-plaintext highlighter-rouge">tests</code> with different folders in it.</p>

<p><img src="/images/wordpress/Tests.png" alt="Tests" /></p>

<p>There are 3 different folders (called suites) to store tests: <strong>acceptance</strong>, <strong>functional</strong>, and <strong>unit</strong>. For our purposes we will need only the <strong>acceptance</strong> suite. Acceptance tests will replay our actions in browser.</p>

<p>To speed up the tests we are not using real browser here, but we use its emulator, a so-called PHPBrowser, based on curl calls.</p>

<h3 id="first-test">First Test</h3>

<p>Let’s create a test named “SubmitPost”. We will need <code class="language-plaintext highlighter-rouge">generate:cept</code> command for that.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar generate:cept acceptance SubmitPost</code></pre></figure>

<p>A newly generated test will look like this:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'perform actions and see result'</span><span class="p">);</span>

<span class="cp">?&gt;</span></code></pre></figure>

<p>This PHP code is written in the way you would describe your actions while you are testing a plugin. What we will actually try to check? Let’s define a scenario:</p>

<ul>
  <li>enter a site</li>
  <li>go to “submit posts” page</li>
  <li>fill all fields</li>
  <li>submit a post</li>
  <li>check a message for valid submission is shown</li>
  <li>admin should see the post</li>
  <li>and publish it</li>
  <li>post should be seen on site</li>
</ul>

<p>Lets write the first step into a test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>

<span class="cp">?&gt;</span></code></pre></figure>

<p>We moved to the front page of a site:</p>

<p><img src="/images/wordpress/WordPress.png" alt="WordPress" /></p>

<p>To move to the “submit posts” page (our step #2) we will need to click on “Submit a Post” menu item:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>

<span class="cp">?&gt;</span></code></pre></figure>

<p>That’s right, everything is as simple as you would tell it to a mate. 
As we are on page submission page we got a form and a few fields to fill in.</p>

<p><img src="/images/wordpress/Submit.png" alt="Submit" /></p>

<p>We are going to publish the review for the “Game of Drones” book  into related category. Follow the code:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'Post Category'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>After a post is submitted a message <code class="language-plaintext highlighter-rouge">Success! Thank you for your submission.</code> is shown.</p>

<p><img src="/images/wordpress/Sent.png.png" alt="Sent" /></p>

<p>Our test wouldn’t be a real test without at least one verification. The result of our current actions is this “Success” message. If we don’t see it on a screen, we assume that test failed.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'Post Category'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Success! Thank you for your submission.'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="execute-test">Execute Test</h2>

<p>As we have one assertion with the <code class="language-plaintext highlighter-rouge">see</code> command in the end, it’s a good idea to try this test in action.
As it was said, we will execute this test with the PHPBrowser, i.e. browser emulator. 
We should point it to the right URL to access our site. For such parameters a config file <code class="language-plaintext highlighter-rouge">acceptance.suite.yml</code> exists.</p>

<p><img src="/images/wordpress/Config.png" alt="Config" /></p>

<p>We need to start a web server and specify proper local url of wordpress site with a plugin we are testing.
We are ready to execute this test with <code class="language-plaintext highlighter-rouge">run</code> command.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar run</code></pre></figure>

<p>And ups…</p>

<p><img src="/images/wordpress/TestFailed.png" alt="TestFailed" /></p>

<p>Looks like everything were ok, before we tried to select option <code class="language-plaintext highlighter-rouge">Post Category</code>. We saw in previous screen, there was such field in a list, but why WebGuy couldn’t find it on a page? It was there.</p>

<p>Well, here is the answer. WebGuy tries to fetch a form element by its label, whenever a label tag has attribute <code class="language-plaintext highlighter-rouge">for</code> that points to the <code class="language-plaintext highlighter-rouge">id</code> of a field , we can select this field by label.</p>

<p><img src="/images/wordpress/SelectField.png" alt="SelectField" /></p>

<p>But as you see, unlike the previous <em>Post Tags</em> field, the <em>Post Category</em> select tag doesn’t have an <code class="language-plaintext highlighter-rouge">id</code>. Thus, the label do not point to it, as we would expect.</p>

<p>How do we resolve this situation? If we can’t match the field by its label, we can probably match it by CSS, pretty similar to how we would do that in jQuery:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'select[name=user-submitted-category]'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Let’s execute the test once again… And we see it has passed.</p>

<p><img src="/images/wordpress/Passed.png" alt="Passed" /></p>

<p>Great, still we only verified the “Success” message was shown. We didn’t check that admin can actually see the user submitted post. This is where we start the next part of this tutorial.</p>

<p>The final test code we got today is:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"> 
<span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'submitted a post by user and publish it as admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit a Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your Name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Your URL'</span><span class="p">,</span><span class="s1">'https://drone-rules.com'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Title'</span><span class="p">,</span> <span class="s1">'Game of Drones Review'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Tags'</span><span class="p">,</span> <span class="s1">'review book rob-starkraft'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">selectOption</span><span class="p">(</span><span class="s1">'select[name=user-submitted-category]'</span><span class="p">,</span> <span class="s1">'Game of Drones'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Post Content'</span><span class="p">,</span> <span class="s1">'This story is epic and characters are amazing.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Submit Post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Success! Thank you for your submission.'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see it is pretty straight forward. And there is nothing hard in writing such tests. But execution of this test took much less then we would reproduce this steps manually, in a browser. Also we can replay this test in any time. Isn’t that a good reason to start testing today?</p>

<h3 id="in-next-series">In Next Series:</h3>

<ul>
  <li>We will finish the test to verify that admin can publish user submitted post.</li>
  <li>We will rework the test make it even more compact and readable.</li>
  <li>We will learn how to deal with data in Codeception.</li>
</ul>

<p>Before we proceed, try to reproduce the following steps locally and prepare the testing environment. You can <a href="https://github.com/Codeception/WordPress-plugin-testing/archive/lesson-1.zip">download this demo project</a> or <a href="https://github.com/Codeception/WordPress-plugin-testing/tree/lesson-1">clone it from GitHub</a>. And try to write and run some tests on your own.</p>

<p><a href="https://codeception.com/08-01-2013/testing-wordpress-plugins-2.html"><strong>Continue to Part2 &gt;</strong></a></p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.4: PageObjects and Friends</title>
      <link>https://codeception.com/07-18-2013/codeception-pageobjects-and-friends.html</link>
      <pubDate>Thu, 18 Jul 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-18-2013/codeception-pageobjects-and-friends</guid>
      <description><![CDATA[ <p>Another release that despite the minor version change brings major improvements. Meet <code class="language-plaintext highlighter-rouge">1.6.4</code>, which adds lots of new ways to customize your test automation platform and improve your tests. And yes, before reading this post take a cup of coffee. We prepared lots of features for you and this long post.</p>

<h2 id="pageobjects">PageObjects</h2>

<p>Long awaited feature of adding PageObjects into the core.
Codeception looks pretty different from other testing frameworks in Java or Ruby.
So it was hard to understand in which way the PageObject should be implemented.</p>

<p>Actually you can think of a PageObject that is just a storage of UI locators (UI Map).</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">ArticlesPage</span> <span class="p">{</span>

	<span class="k">const</span> <span class="no">URL</span> <span class="o">=</span> <span class="s1">'/articles'</span><span class="p">;</span>

	<span class="k">static</span> <span class="nv">$articleList</span> <span class="o">=</span> <span class="s1">'#list'</span><span class="p">;</span>
	<span class="k">static</span> <span class="nv">$newArticleButton</span> <span class="o">=</span> <span class="s1">'#toolbar a.new'</span><span class="p">;</span>

	<span class="k">static</span> <span class="k">function</span> <span class="n">row</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="k">return</span> <span class="nv">$articleList</span> <span class="mf">.</span><span class="s2">" .article-</span><span class="nv">$id</span><span class="s2">"</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In a test you can use such PageObject this way:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'find article #1 in a list and edit it'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="nc">ArticlesPage</span><span class="o">::</span><span class="no">URL</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeElement</span><span class="p">(</span><span class="nc">ArticlesPage</span><span class="o">::</span><span class="nv">$articleList</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Edit'</span><span class="p">,</span> <span class="nc">ArticlesPage</span><span class="o">::</span><span class="nf">row</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Editing Article #1'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>But how to make PageObjects actually to define page interaction too?
Can we improve that? Sure! In a test they may look like:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'find article #1 in a list and edit it'</span><span class="p">);</span>
<span class="nc">ArticlesPage</span><span class="o">::</span><span class="nf">of</span><span class="p">(</span><span class="nv">$I</span><span class="p">)</span>
	<span class="o">-&gt;</span><span class="nf">visit</span><span class="p">()</span>
	<span class="o">-&gt;</span><span class="nf">openArticleForEditing</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Editing Article #1'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>We have moved some logic into the PageObject class, and so we can reuse its methods in other tests.
<a href="https://codeception.com/docs/07-AdvancedUsage#PageObjects">Read more on generating PageObjects on newly updated Guides page</a>.</p>

<h2 id="stepobject">StepObject</h2>

<p>Alternatively, interaction logic can be kept in StepObject classes. In which we recommend to define actions that may require passing through several pages. Also it may be useful if you want to define actions based on user roles.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy\AdminSteps</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">am</span><span class="p">(</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create a new admin and check his account'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">logIntoAdminArea</span><span class="p">();</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">createUser</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">,</span><span class="s1">'123456'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">logout</span><span class="p">();</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">login</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">,</span><span class="s1">'123456'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInCurrentUrl</span><span class="p">(</span><span class="s1">'/admin'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">AdminSteps</code> class inherits from <code class="language-plaintext highlighter-rouge">WebGuy</code> class, thus you have common actions from modules, as well as newly defined customized actions like <code class="language-plaintext highlighter-rouge">createUser</code>, <code class="language-plaintext highlighter-rouge">login</code>, <code class="language-plaintext highlighter-rouge">logout</code> in your tests.</p>

<p><a href="https://codeception.com/docs/07-AdvancedUsage#StepObjects">StepObjects are now in Guides too.</a></p>

<h2 id="groups--extensions">Groups &amp;&amp; Extensions</h2>

<p>Now it is possible to include 3rd party code into Codeception. Current options are pretty limited, you can extend Codeception only by listening to its internal events. Why do you need that? Not sure. But check out our <a href="https://github.com/Codeception/Notifier">Notifier</a> extension that we prepared to demonstrate the power of extensions. Also you can develop your own <a href="https://github.com/Codeception/Codeception/blob/master/tests/data/claypit/tests/_data/MyOutputFormatter.php">alternative output formatter</a>.</p>

<p>Group Classes are special extensions, that listen to events from a tests of a specific group. Thus, they are very if some tests require common environment setup. Group classes are also good for loading fixtures.</p>

<p>Here is the sample group class:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">AdminGroup</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Platform\Group</span> <span class="p">{</span>

    <span class="k">static</span> <span class="nv">$group</span> <span class="o">=</span> <span class="s1">'admin'</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">_before</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\Event\Test</span> <span class="nv">$e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">writeln</span><span class="p">(</span><span class="s2">"Preparing for [admin] test..."</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">_after</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\Event\Test</span> <span class="nv">$e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">writeln</span><span class="p">(</span><span class="s2">"Finishing [admin] test..."</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><a href="https://codeception.com/docs/08-Customization#Extension-classes">Read more about Groups and Extensions</a>.</p>

<h2 id="conditional-asserts">Conditional Asserts</h2>

<p>Pretty simple, yet useful feature when you want your test not to be stopped on failure.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">canSee</span><span class="p">(</span><span class="s1">'Hello World'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello World'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This two assertions do just the same, but if <code class="language-plaintext highlighter-rouge">canSee</code> fails to match ‘Hello World’ text on a page, it doesn’t stop the test. Still failed assertion will be displayed in final report.</p>

<p><a href="https://codeception.com/docs/04-AcceptanceTests#Conditional-Assertions">Guides section about that</a>.</p>

<h3 id="assertion-failure-messages-improved">Assertion Failure Messages Improved</h3>

<p>For most Framework and Mink modules we improved the error messages that happen on failures. No more mystic messages like <code class="language-plaintext highlighter-rouge">failed asserting that 0 greater then 0</code>. Better exceptions with better error reports.</p>

<h3 id="comments-simplified">Comments Simplified</h3>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="p">[</span><span class="s1">'comments can be easily added to a test'</span><span class="p">];</span>
<span class="nv">$I</span><span class="p">[</span><span class="s1">'and displayed in output when executed'</span><span class="p">];</span>
<span class="nv">$I</span><span class="p">[</span><span class="s1">'and added to HTML reports'</span><span class="p">];</span>
<span class="nv">$I</span><span class="p">[</span><span class="s1">'pretty cool when you follow BDD or ATDD'</span><span class="p">];</span>
<span class="nv">$I</span><span class="p">[</span><span class="s1">'describe everything in comments and then automate them'</span><span class="p">];</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h3 id="minor-fixes-and-improvements">Minor Fixes and Improvements</h3>

<ul>
  <li>codecoverage for multiple runner is now stored into right dir, thanks <strong>piccagliani</strong>.</li>
  <li>header actions were added to <strong>REST</strong> module by <strong>brutuscat</strong>.</li>
  <li>added environment management to <strong>Symfony2</strong> module by <strong>SimonEast</strong>.</li>
</ul>

<h3 id="update">Update</h3>

<p><strong>It is very important to execute “build” after the update</strong>.
Also this update has lots of changes, if you have an issues with them, please report them to Github.
If you have issues updating, fall back to previous version for now.
We are planning to introduce more humane stability politics soon. Wait for announcements.</p>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.3 is out</title>
      <link>https://codeception.com/06-23-2013/codeception-1-6-3.html</link>
      <pubDate>Sun, 23 Jun 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-23-2013/codeception-1-6-3</guid>
      <description><![CDATA[ <p>** Update: Yii2 module was included in release. See details below.**</p>

<p>It was a one-month release sprint and probably this release took much longer then we expected.
1.6.3 release introduces lots of features, internal unit tests, and internal refactorings. Please take a cup of coffee because we prepared a long story of features you can try in 1.6.3.</p>

<p>The major internal change you should be aware of is upgrade to <strong>Symfony Components 2.3</strong>. This may introduce some instability, or conflicts (if you use previous Symfony version), but the good news are that: Symfony 2.3 is LTS, so we are going to stay on this version for a long time.</p>

<h2 id="one-runner">One-Runner</h2>

<p>This feature was expected by <strong>Symfony2</strong> users, as well as other developers who uses several independent applications in a project (as Symfony bundles are). From now on you are not limited to execute tests from only one directory. In Codeception 1.6.3 you can create a meta-config and make it to point to other codeception test configs:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">include</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">frontend</span>
  <span class="pi">-</span> <span class="s">admin</span>
  <span class="pi">-</span> <span class="s">api/rest</span>
<span class="na">paths</span><span class="pi">:</span>
  <span class="na">log</span><span class="pi">:</span> <span class="s">log</span></code></pre></figure>

<p>In this <code class="language-plaintext highlighter-rouge">codeception.yml</code> we include tests configs from <code class="language-plaintext highlighter-rouge">frontend</code>, <code class="language-plaintext highlighter-rouge">admin</code>, and <code class="language-plaintext highlighter-rouge">app/rest</code> directories. By executing tests from it, we will launch all test suites from this applications.</p>

<p><a href="https://codeception.com/docs/08-Customization">More about it…</a></p>

<p>Symfony2 users now can create a test suite for each bundle they have and then execute all tests in meta config.</p>

<h2 id="namespaces">Namespaces</h2>

<p>If you decided to use a multiple-config option, the first issue you get is conflict of Helper classes and Guy classes. It’s natural to use namespaces to separate those classes of multiple applications. From now on, you can <a href="https://codeception.com/docs/08-Customization#Namespaces">assign a namespace</a> for your test classes.</p>

<h2 id="facebook-module">Facebook Module</h2>

<p>Thanks to <strong>Tiger-seo</strong> we got a module that might be very handy for all developers that work with Facebook API.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ApiGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">am</span><span class="p">(</span><span class="s1">'Guest'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantToTest</span><span class="p">(</span><span class="s1">'check-in to a place be published on the Facebook using API'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveFacebookTestUserAccount</span><span class="p">();</span>
<span class="nv">$accessToken</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabFacebookTestUserAccessToken</span><span class="p">();</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveHttpHeader</span><span class="p">(</span><span class="s1">'Auth'</span><span class="p">,</span> <span class="s1">'FacebookToken '</span> <span class="mf">.</span> <span class="nv">$accessToken</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'send request to the backend, so that it will publish on user\'s wall on Facebook'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendPOST</span><span class="p">(</span><span class="s1">'/api/v1/some-api-endpoint'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seePostOnFacebookWithAttachedPlace</span><span class="p">(</span><span class="s1">'167724369950862'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Don’t leave your Facebook applications untested! With this module you can log in as test user and perform interactions using REST API or HTTP calls.</p>

<p><a href="https://codeception.com/docs/modules/Facebook">Facebook Module Referenace</a></p>

<h2 id="helper-customizations">Helper Customizations</h2>

<p>Before 1.6.3 Helpers was loaded with simple <code class="language-plaintext highlighter-rouge">include_once</code> call. I.e., there was no other option then to load them from <code class="language-plaintext highlighter-rouge">tests/_helpers</code> directory. In 1.6.3 we replaced this call with autoloader, and also we added a global <code class="language-plaintext highlighter-rouge">_bootstrap.php</code> file in which you can prepend any code before helpers are loaded.</p>

<p><a href="https://codeception.com/docs/08-Customization">More about autoloading Helpers</a>.</p>

<p>Also in 1.6.3 you can customiza which methods of module or helper should be imported into Guy class. In other words, you can enable or disable module methods. If your helper is extended from one of standard modules, you can disable usage of inherited methods and implement them on your own. It is especially useful if you want to rename parent class methods:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">SecondDbHelper</span> <span class="kd">extends</span> <span class="nc">Db</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="nv">$includeInheritedActions</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">seeInSecondDb</span><span class="p">(</span><span class="nv">$table</span><span class="p">,</span> <span class="nv">$data</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">seeInDatabase</span><span class="p">(</span><span class="nv">$table</span><span class="p">,</span> <span class="nv">$data</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>    
<span class="cp">?&gt;</span></code></pre></figure>

<p>More on <a href="https://codeception.com/docs/03-ModulesAndHelpers#Extension-options">helper customization</a>.</p>

<h2 id="stubs-with-mock-matchers">Stubs with Mock matchers.</h2>

<p>Codeception’s utility Stub class got lots of improvements by <strong>svsool</strong>. Mock matching was also added into it, thus you may use shorter mock syntax in your unit tests:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Util\Stub</span><span class="p">;</span>
<span class="c1">// example 1</span>
<span class="nv">$mock</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmpty</span><span class="p">(</span><span class="s1">'SomeClass'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'trackInvocationCount'</span> <span class="o">=&gt;</span> 
     <span class="nc">Stub</span><span class="o">::</span><span class="nf">once</span><span class="p">(</span><span class="k">function</span><span class="p">()</span> <span class="p">{</span><span class="k">return</span> <span class="kc">true</span><span class="p">})),</span>
     <span class="nv">$this</span><span class="p">);</span>

<span class="nv">$mock</span><span class="o">-&gt;</span><span class="nf">trackInvocationCount</span><span class="p">();</span>

<span class="c1">// example 2</span>
<span class="nv">$mock</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmpty</span><span class="p">(</span><span class="s1">'SomeClass'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'methodNeverCalled'</span><span class="p">,</span>  <span class="nc">Stub</span><span class="o">::</span><span class="nf">never</span><span class="p">(),</span> <span class="nv">$this</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Complete reference is coming soon.</p>

<h2 id="execute-call">Execute Call</h2>

<p>In case you need to execute custom code in a test, you can now use the <code class="language-plaintext highlighter-rouge">execute</code> method for that:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span> 
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">execute</span><span class="p">(</span><span class="k">function</span><span class="p">()</span> <span class="p">{</span>
  <span class="no">DB</span><span class="o">::</span><span class="nf">updateCounters</span><span class="p">();</span>
<span class="p">});</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">execute</code> method is declared in Guy class itself, thus it can be used anywhere without attaching a module. 
As you know, Codeception tests files are included 2 times: one for parsing and for execution. Calls inside <code class="language-plaintext highlighter-rouge">execute</code> method will be triggered only on test execution.</p>

<p>Thanks <strong>korotovsky</strong> for implementation.</p>

<h2 id="yii2-module">Yii2 module</h2>

<p><img src="https://static.yiiframework.com/css/img/logo.png" alt="Yii Framework" style="float: right" /></p>

<p>Yii framework hits its second major version. Yii 2.0 was developed with testing in mind. 
Despite the fact that Yii 2.0 is still in its early days, we got <a href="https://codeception.com/docs/modules/Yii2">a working Yii2 module</a> for it.
Unlike most of framework modules of Codepception, this one was created by Yii core developer <strong>qiangxue</strong>.</p>

<p>We are excited of collaboration with Yii Framework core team. And we wish them Yii 2.0 project to hit stable release soon.</p>

<h2 id="various-ehancements-and-fixes">Various Ehancements and Fixes.</h2>

<ul>
  <li><code class="language-plaintext highlighter-rouge">--no-colors</code> runner option by <strong>igorsantos07</strong>.</li>
  <li>fix to double text in <code class="language-plaintext highlighter-rouge">generate:scenarios</code>.</li>
  <li>ZF1 sessions and auth helpers fixed by <strong>brutuscat</strong></li>
  <li><code class="language-plaintext highlighter-rouge">seeInDatabase</code> can check that table is empty with: <code class="language-plaintext highlighter-rouge">seeInDatabase('empty_table')</code> by <strong>igorsantos07</strong>.</li>
  <li><code class="language-plaintext highlighter-rouge">ZombieJS</code> updates by <strong>synchrone</strong>.</li>
</ul>

<p>additionally we had lots of fixes to Db module and its drivers. Sorry, we can’t list all of them here.</p>

<p>As it was said we had internal refactorings, to make code stable and clearer.
Soon we plan to publish a complete blog on Codeception internals.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<p><strong>Release sponsored by 2AmigOS</strong></p>

<p><img src="https://2amigos.us/img/logo.png" alt="2AmigOS" /></p>

 ]]></description>
    </item>
    
    <item>
      <title>Getting on Testing Ship</title>
      <link>https://codeception.com/06-12-2013/getting-on-testing-ship.html</link>
      <pubDate>Wed, 12 Jun 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-12-2013/getting-on-testing-ship</guid>
      <description><![CDATA[ <p>In this blogpost we will try to figure out how to get faster into the testing. What tests to write at first?
Let’s say we already have a project and we didn’t practice TDD/BDD developing it. Should we ignore testing at all? Definitely no. So where should we start then?</p>

<h3 id="meet-the-pyramid">Meet the Pyramid</h3>

<p>There is a very basic schema for proper the testing suite. It is called the <strong>Pyramid of Testing</strong>.</p>

<p><img src="https://dl.dropboxusercontent.com/u/930833/CodeceptionHotcodePresentation/pictures/pyramid.png" alt="Testing Pyramid" /></p>

<p>This concept was originally proposed by <a href="https://www.amazon.com/gp/product/0321579364">by Mike Cohn, his book “Succeeding with Agile”</a> and became the one of the fundamentals in testing. In this schema all tests are divided into 3 or 4 layers and states the dependencies for those layers. You won’t build a pyramid having only top and bottom of it. That means that your acceptance tests depend on your integration (functional) tests, and they depend on unit tests. Also pyramid shows you the proportion for tests that should be written. You should have lots of unit tests, some functional, and few of acceptance.</p>

<h3 id="when-to-skip-unit-tests">When to skip unit tests.</h3>

<p>In web development with PHP we are not building the software from scratch. 
We use frameworks and content management systems and to create web sites and applications on top of them.</p>

<p>For platforms like Drupal or Wordpress we can’t unit test our application at all. And even modern PHP frameworks may not help you with unit testing. Tracking and mocking dependencies, especially in controllers can become a pain. If you feel that it takes for you too long for writing unit tests, skip them for now.</p>

<p><strong>There is nothing wrong to start testing with no unit test actually written.</strong> Inability to write unit tests, should not be excuse for not testing at all. If you develop web application with CMS or framework, you can rely on its internals, thus you can assume that you are already using its unit tests in your pyramid’s basement.</p>

<p>If you can’t figure out how to test the most important application parts on the unit level, try to cover it with functional tests.</p>

<h3 id="getting-it-tested-with-codeception">Getting it tested with Codeception</h3>

<p><em>If you are new to Codeception, <a href="https://codeception.com/docs/02-GettingStarted">check our guides</a>.</em></p>

<p>We recommend to start with <strong>covering most crucial parts of your application with functional tests</strong>, <a href="https://codeception.com/docs/05-FunctionalTests#Frameworks">if your framework supports them</a>. Be aware, that stability of framework modules in Codeception can vary. If Codeception does not have a module for your framework, you can stick to <a href="https://codeception.com/docs/modules/PhpBrowser">PhpBrowser</a>. Actually you should think of it as level of functional / integration testing. It does not work with GUI, it does not require a browser, thus it runs much faster then acceptance tests. So if you don’t plan to use one of the frameworks module, place PhpBrowser to functional testing suite and use TestGuy to manipulate it.</p>

<p>When your most important functionality is covered with functional tests, you should cement the basement with unit tests and build a top with Selenium acceptance tests.</p>

<p>At first try to keep tested the most important parts of your application. If you can do that with units, you are the hero! If not, try to do it on functional testing level, if still no, PhpBrowser is your choice. But please do not start testing with Selenium tests!</p>

<p>Then you should extend your testing suite to cover more and more parts. Please remember the pyramid, and use code coverage reports to track which code parts are still terra incognita.</p>

<p>Happy testing.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Sponsorship Announcement</title>
      <link>https://codeception.com/06-03-2013/2amigos-sponsorship-announcement.html</link>
      <pubDate>Mon, 03 Jun 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-03-2013/2amigos-sponsorship-announcement</guid>
      <description><![CDATA[ <p><img src="https://2amigos.us/img/logo.png" style="float: right" /></p>

<p>We are pleased to make a special announcement, today. From now on <strong>the development of Codeception will be sponsored by <a href="https://2amigos.us/">2amigOS!</a></strong>, a web development and consultancy company from Miami. They are widely known in the <strong>Yii</strong> community by <a href="https://github.com/2amigos">their open source works</a>. They use Codeception in their daily development, as well as recommend it to their clients. They decided give back to provide a sponsorship to our testing framework.</p>

<p>What does this mean for the Codeception project? You can be certain that nothing is changing with the development process or license, and Codeception will remain absolutely free and open source with MIT license. Essentially, this means that now, <strong>Michael Bodnarchuk “Davert”</strong>, will get more time to devote to it to make it even more robust.</p>

<p>What does this mean for you, Codeception users? This means that Codeception is making a serious step towards becoming a professional testing tool.
However, being professional also requires some reliability and more efficient support, marketing, and business strategy. Certainly, that is not a task one person (or Codegyre developer team) could handle. With this partnership we will improve the support, documentation and definitely will start to bring more features to this product. Also, as some point in the future we will launch commercial support and trainings (for those who are interested in them).</p>

<p>The only term <a href="https://2amigos.us/">2amigOS!</a> have asked for their sponsorship was a small refactoring in code. You will need to update your tests according to this example:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// for acceptance tests</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebAmigo</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>

<span class="c1">// for functional tests</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestAmigo</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>

<span class="c1">// for api tests</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ApiAmigo</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Just kidding :) Instead of renaming Guy classes, we decided to thank <a href="https://2amigos.us/">2amigOS!</a> by putting their logo on the site to show their support and dedication.</p>

<p><em>We are looking forward to some great new things and a good future, so… 
Please spread the word about Codeception. Encourage your friends to try it, and add your company to <a href="https://github.com/Codeception/Codeception/wiki/Who-is-using-it%3F">this list</a>. Thanks for those who are already using it, and special thanks for those of you who contribute.</em></p>

<p>P.S. Btw, don’t miss <strong>Nettuts+ course on Codeception</strong> which started today. <a href="https://tutsplus.com/course/modern-testing-in-php-with-codeception/">Take your seats</a> and say thanks to Jeffrey Way for it.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.2: Subdomains Support</title>
      <link>https://codeception.com/05-25-2013/subdomains-release.html</link>
      <pubDate>Sat, 25 May 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-25-2013/subdomains-release</guid>
      <description><![CDATA[ <p>Looks like a good time for a new release. We decided to stick to features that was asked a lot and to merge all uesful PRs that were submitted.</p>

<p>One of them is <strong>Subdomain support</strong>. If you were wondering how to deal with subdomains of your app, we have a new <code class="language-plaintext highlighter-rouge">amOnSubdomain</code> command for you. It will prepend a subdomain name to your current url you put in config.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// configured url is http://user.site.com</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnSubdomain</span><span class="p">(</span><span class="s1">'user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="c1">// moves to http://user.site.com/</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>But… well, this would be much easier to implement by anyone if only you had an option to dynamically pass configuration to modules. And yes, it’s also possible now. You can use new <code class="language-plaintext highlighter-rouge">_reconfigure</code> method of a module. In helper you can access it and replace the keys with required values.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'Selenium2'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">_reconfigure</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'browser'</span> <span class="o">=&gt;</span> <span class="s1">'chrome'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In the end of a test, all changed options will be rolled back to configuration values.</p>

<p>Some new nice improvements and fixes from our contributors:</p>

<ul>
  <li>Cookie methods like <code class="language-plaintext highlighter-rouge">getCookie</code>, <code class="language-plaintext highlighter-rouge">setCookie</code> can now be used in acceptance tests (thanks <strong>igorsantos07</strong>)</li>
  <li>Curl options are now correctly passed to PhpBrowser (thanks to <strong>mrtimp</strong>)</li>
  <li>Also <code class="language-plaintext highlighter-rouge">X-Requested-With</code> is cleared in Ajax requests of PhpBrowser (thanks to <strong>vinu</strong>)</li>
  <li>Non-strict matching for links (with <code class="language-plaintext highlighter-rouge">normalize-space</code> XPath) was proposed by <strong>brutuscat</strong>.</li>
  <li>Symfony1 module fixed (by <strong>walkietalkie</strong>)</li>
  <li>Lots of small fixes and tests by <strong>Ragazzo</strong>.</li>
  <li>fix to <code class="language-plaintext highlighter-rouge">haveInDatabase</code> method by davert.</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Continuous Integration In Practice: Codeception, Jenkins, Xvfb</title>
      <link>https://codeception.com/05-24-2013/jenkins-ci-practice.html</link>
      <pubDate>Fri, 24 May 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-24-2013/jenkins-ci-practice</guid>
      <description><![CDATA[ <p><img src="https://jenkins-ci.org/sites/default/files/images/headshot.png" style="float: left;" />
<em>Another guest post from <strong>Ragazzo</strong> containing some practical tips on configuring CI server. If you ever wanted to ask how you could use Codeception with Jenkins, you are in a right place.</em></p>

<p>It is very good to automate maximum of the things you can. Once we automated testing process, build should be automated too. I use <a href="https://www.jenkins.io/">Jenkins</a> as my primary continuous integration server. It can be installed and executed on all popular operating systems with Java enabled.</p>

<p>As for PHPUnit I use <strong>JUnit</strong> format for error reports and some <strong>Jenkins</strong> plugins to make it work with Code Coverage. For <strong>Behat</strong> and <strong>Codeception</strong> I also use JUnit output log format and <a href="https://jenkins-php.org/">Jenkins PHPUnit Plugin</a>.</p>

<p>Thus, my application have 4 jobs in Jenkins they named in that way:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">MyProject_Testing_Unit</code> # via phpunit</li>
  <li><code class="language-plaintext highlighter-rouge">MyProject_Testing_Func</code> # via behat</li>
  <li><code class="language-plaintext highlighter-rouge">MyProject_Testing_Func_Web</code>  # codeception functional</li>
  <li><code class="language-plaintext highlighter-rouge">MyProject_Testing_Accep_Web</code> # codeception acceptance</li>
</ul>

<p>And of course one job for bulding packages for demo and for developer:</p>

<ul>
  <li>MyProject_Build_Dist</li>
</ul>

<p>I scheduled jobs to run one by one so the first goes <code class="language-plaintext highlighter-rouge">Unit</code>, then it triggers <code class="language-plaintext highlighter-rouge">Func</code>, then <code class="language-plaintext highlighter-rouge">Func</code> triggers <code class="language-plaintext highlighter-rouge">Func_Web</code> and so on. <code class="language-plaintext highlighter-rouge">Build</code> is not triggered automatically, I start it by myself.</p>

<h3 id="configuring-builds">Configuring Builds</h3>

<p>Lets pay attention on two of them that include Codeception. I’m using <strong>Ant</strong> build tool to execute them.
Bascially for JUnit output you need nothing more then running codeception with <code class="language-plaintext highlighter-rouge">--xml</code> option. Like this:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">codecept.phar <span class="nt">--xml</span> run functional</code></pre></figure>

<p>This will produce the <code class="language-plaintext highlighter-rouge">report.xml</code> file in <code class="language-plaintext highlighter-rouge">tests/_log</code> directory, which will be analyzed by Jenkins. In my Ant task I’m also clearing a _log directory before running tests.</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;project</span> <span class="na">name=</span><span class="s">"MyProject_Testing_Func_Web"</span> <span class="na">default=</span><span class="s">"build"</span> <span class="na">basedir=</span><span class="s">"."</span><span class="nt">&gt;</span>
<span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"clean"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;delete</span> <span class="na">dir=</span><span class="s">"${basedir}/build/src/protected/tests/codeception/tests/_log"</span> <span class="na">includes=</span><span class="s">"**/*"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/target&gt;</span>
<span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"codeception"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;exec</span> <span class="na">dir=</span><span class="s">"${basedir}/build/src/protected/tests/codeception"</span> <span class="na">executable=</span><span class="s">"php"</span> <span class="na">failonerror=</span><span class="s">"true"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;arg</span> <span class="na">line=</span><span class="s">"codecept.phar --xml run functional"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;/exec&gt;</span>
<span class="nt">&lt;/target&gt;</span>
<span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"build"</span> <span class="na">depends=</span><span class="s">"clean, codeception"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/project&gt;</span></code></pre></figure>

<p>Also you may want to add the <code class="language-plaintext highlighter-rouge">--html</code> option for execution. That would produce a readable HTML report, that you can show to your boss. You will need <a href="https://wiki.jenkins-ci.org/display/JENKINS/HTML+Publisher+Plugin">HTML Publisher Plugin</a> to display it in Jenkins web interface.</p>

<h3 id="using-selenium2-and-xvfb">Using Selenium2 and Xvfb</h3>

<p>To run acceptance web tests correctly on server you don’t need to install desktop environment like Gnome or XFCE just to launch a browser. Better to use Virtual Framebuffer <a href="https://en.wikipedia.org/wiki/Xvfb">Xvfb</a> for running Selenium tests without showing them on screen.</p>

<p>You need to install Xfvb and then run Selenium2 with this options:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">export </span><span class="nv">DISPLAY</span><span class="o">=</span><span class="s2">":1"</span> <span class="o">&amp;&amp;</span> java <span class="nt">-jar</span> selenium-server-standalone.jar</code></pre></figure>

<p>Then start your Codeception acceptance tests as usual. By the way, I suggest you to use <a href="https://gist.github.com/jterrace/2911875">this Xvfb init script</a> in Ubuntu.</p>

<p><em>There is nothing hard in setting up Jenkins. You can use Codeception with it or in any other CI server. If you already did that, please share your experience with community. We really need more personal experiences and blogposts from the community. Documentation can’t cover all use cases, that’s why your thought are much appreciated. If you don’t have a blog we can publish your blogpost here.</em></p>

<p>P.S. Just to mention, If you are using <strong>Bamboo</strong> CI server, pls enable the <code class="language-plaintext highlighter-rouge">--no-exit</code> option to run tests correctly.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Headless Browser Testing with Selenium2 and PhantomJS</title>
      <link>https://codeception.com/05-13-2013/phantom-js-headless-testing.html</link>
      <pubDate>Mon, 13 May 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-13-2013/phantom-js-headless-testing</guid>
      <description><![CDATA[ <p><em>This is a guest blogpost by <a href="https://jonstuff.blogspot.com/">Jon Phipps</a>. Jon explains how to use PhantomJS – the most anticipated testing backend in Codeception.</em></p>

<p>If you’re running acceptance tests in <a href="https://codeception.com/">Codeception</a> that require interaction with JavaScript, or have scripts that manipulate the DOM, the speedy <a href="https://codeception.com/docs/modules/PhpBrowser">Php Browser</a> driver won’t help you since it doesn’t support JavaScript. The best options for running tests using JavaScript are the <a href="https://codeception.com/docs/modules/Selenium2">Selenium2</a> and <a href="https://codeception.com/docs/modules/ZombieJS">ZombieJS</a> drivers.</p>

<p>The <strong>Selenium2</strong> driver actually loads and runs an active browser session, manipulating the browser just as a human would. <strong>ZombieJS</strong> is a ‘headless’ browser that provides all of the features of a regular browser, but without a display interface. Without the extra time spent waiting for the display to actually render, a headless browser like ZombieJS can run far faster than a normal browser, so you’re tests will execute in as little as half the time. But ZombieJS requires installing Node.js and can be a little buggy, plus it has its own API (which has both pros and cons). The Selenium2 driver is well tested and implements a standard API – the <strong>WebDriver Wire Protocol</strong> – across all of the browsers it has drivers for.</p>

<p>Now there’s a headless browser that includes a WebDriver Wire Protocol implementation – <strong><a href="https://phantomjs.org/index.html">PhantomJS</a></strong>. The latest version of PhantomJS is an easy to install, stand-alone binary that doesn’t require installing Node.js or any other dependencies, and ships with its own <strong>‘Ghost Driver’</strong> for implementing the WebDriver Wire Protocol. Which means you can drive it using the Selenium2 driver in Codeception, and anything that you can test in Chrome, Firefox, Safari, or IE using Selenium2, you can now test in half the time using PhantomJS</p>

<p>Even though it’s not needed to run the most recent PhantomJS, it’s a good idea to have Selenium2 installed so you can test in other browsers. If you haven’t installed Selenium2, you just need to follow the <a href="https://codeception.com/docs/modules/Selenium2">instructions</a> on the Codeception web site for installing and running the Selenium2 driver. It’s pretty simple, but totally optional.</p>

<p>To get started with PhantomJS, just <a href="https://phantomjs.org/download.html">download PhantomJS</a>. The binary is setup and ready to use for Linux, Mac OSX, and Windows. Put it, or a symlink to it, somewhere in your path so you can launch it from anywhere.</p>

<p>You’re done with installation!</p>

<p>Next, open up a new terminal window and launch PhantomJS, telling it to use the its built-in WebDriver extension to use the port Codeception is listening to (4444 is the default), and leave the window open:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>phantomjs <span class="nt">--webdriver</span><span class="o">=</span>4444</code></pre></figure>

<p>You should see a response like this in your terminal:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">PhantomJS is launching GhostDriver...
<span class="o">[</span>INFO  - 2013-05-10T14:11:05.076Z] GhostDriver - Main - running on port 4444</code></pre></figure>

<p>Now just enable the Selenium2 driver in your <code class="language-plaintext highlighter-rouge">acceptance.suite.yml</code> file and use the browser setting <code class="language-plaintext highlighter-rouge">browser: phantomjs</code> (an example file is on the <a href="https://codeception.com/docs/modules/Selenium2">Selenium2 driver page</a>). If you’re changing <em>modules</em> then you should also run <code class="language-plaintext highlighter-rouge">php codecept.phar build</code>.</p>

<p>Check it out by doing a fresh Codeception run:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php codecept.phar run acceptance</code></pre></figure>

<p>Your tests should now run quietly and silently, and much faster.</p>

<p>You should see some output in your PhantomJS terminal window providing some useful feedback on this session’s capabilities provisioning. This happens on every run (the output below are the defaults):</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="o">[</span>INFO  - 2013-05-10T14:33:43.796Z] Session <span class="o">[</span>9dbc5700-b97e-11e2-8dc9-976d2e8732bf] - 
CONSTRUCTOR - Desired Capabilities:<span class="o">{</span>
  <span class="s2">"browserName"</span> : <span class="s2">"PhantomJS"</span>,
  <span class="s2">"version"</span> : <span class="s2">"9"</span>,
  <span class="s2">"platform"</span> : <span class="s2">"ANY"</span>,
  <span class="s2">"browserVersion"</span> : <span class="s2">"9"</span>,
  <span class="s2">"browser"</span> : <span class="s2">"firefox"</span>,
  <span class="s2">"name"</span> : <span class="s2">"Codeception Test"</span>,
  <span class="s2">"deviceOrientation"</span> : <span class="s2">"portrait"</span>,
  <span class="s2">"deviceType"</span> : <span class="s2">"tablet"</span>,
  <span class="s2">"selenium-version"</span> : <span class="s2">"2.31.0"</span>
<span class="o">}</span>
<span class="o">[</span>INFO  - 2013-05-10T14:33:43.796Z] Session <span class="o">[</span>9dbc5700-b97e-11e2-8dc9-976d2e8732bf] - 
CONSTRUCTOR - Negotiated Capabilities: <span class="o">{</span>
  <span class="s2">"browserName"</span> : <span class="s2">"phantomjs"</span>,
  <span class="s2">"version"</span> : <span class="s2">"1.9.0"</span>,
  <span class="s2">"driverName"</span> : <span class="s2">"ghostdriver"</span>,
  <span class="s2">"driverVersion"</span> : <span class="s2">"1.0.3"</span>,
  <span class="s2">"platform"</span> : <span class="s2">"mac-10.7 (Lion)-32bit"</span>,
  <span class="s2">"javascriptEnabled"</span> : <span class="nb">true</span>,
  <span class="s2">"takesScreenshot"</span> : <span class="nb">true</span>,
  <span class="s2">"handlesAlerts"</span> : <span class="nb">false</span>,
  <span class="s2">"databaseEnabled"</span> : <span class="nb">false</span>,
  <span class="s2">"locationContextEnabled"</span> : <span class="nb">false</span>,
  <span class="s2">"applicationCacheEnabled"</span> : <span class="nb">false</span>,
  <span class="s2">"browserConnectionEnabled"</span> : <span class="nb">false</span>,
  <span class="s2">"cssSelectorsEnabled"</span> : <span class="nb">true</span>,
  <span class="s2">"webStorageEnabled"</span> : <span class="nb">false</span>,
  <span class="s2">"rotatable"</span> : <span class="nb">false</span>,
  <span class="s2">"acceptSslCerts"</span> : <span class="nb">false</span>,
  <span class="s2">"nativeEvents"</span> : <span class="nb">true</span>,
  <span class="s2">"proxy"</span> : <span class="o">{</span>
    <span class="s2">"proxyType"</span> : <span class="s2">"direct"</span>
  <span class="o">}</span>
<span class="o">}</span>
<span class="o">[</span>INFO  - 2013-05-10T14:33:43.796Z] SessionManagerReqHand - _postNewSessionCommand - 
New Session Created: 9dbc5700-b97e-11e2-8dc9-976d2e8732bf</code></pre></figure>

<p>You can adjust these capabilities in your <code class="language-plaintext highlighter-rouge">acceptance.suite.yml</code> file like so:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">modules:
   enabled: <span class="o">[</span>Selenium2]
   config:
      Selenium2:
         url: <span class="s1">'http://localhost/'</span>
         browser: phantomjs
         capabilities:
             webStorageEnabled: <span class="nb">true</span></code></pre></figure>

<p>I have no idea if capabilities from the larger list of Selenium <a href="https://code.google.com/p/selenium/wiki/DesiredCapabilities">DesiredCapabilities</a> that are not on the list you see reported from the driver are enabled for PhantomJS.</p>

<p>Headless testing can be a bit of a challenge, since it’s impossible to ‘see’ what failed. But in this case, Codeceptions default logging and screenshot capture on failure can be extremely helpful, since you can then actually see the state of the browser at the point of failure.</p>

<p>There’s quite a bit more that you can do with PhantomJS. The <a href="https://casperjs.org/index.html">CasperJS</a> project makes good use of the PhantomJS API and if you already have NodeJS installed it’s a quick and easy way to play with some of the PhantomJS capabilities. CapserJS, aside from requiring NodeJS, only drives PhantomJS. So its not a reasonable alternative to Codeception. Maybe at some point there will be a native Mink driver for the PhantomJS API which will more fully exploit it.</p>

<p>Happy testing.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Playng with Cests</title>
      <link>https://codeception.com/05-11-2013/playing-with-cests.html</link>
      <pubDate>Sat, 11 May 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-11-2013/playing-with-cests</guid>
      <description><![CDATA[ <p><em>This is the second guestpost from <strong>Ragazzo</strong>. He writes about using Cest format in functional tests.</em></p>

<p>As you already saw it is easy to use flat Cept files in Codeception for your tests. But what if you want to test CRUD operations so a Cept can take 50-70 rows long. In this case it would not be so “easy-to-read”.</p>

<p>This is where Codeception’s Cests are really good to use. Cests are simple classes with no parents. You can use them like your classic PHPUnit classes. All that need to know is that each <code class="language-plaintext highlighter-rouge">public</code> Cest method is a separated scenario, which could be represented by a Cept file.</p>

<p>The other issue we want to solve with Cest files is <strong>UI mapping</strong>. It’s ok to start testing with relying on button names and field labels. But the more UI elements come to page, the more complex our selectors become. There should be a way to manage those UI elements for tests. It’s better not to put too much CSS/XPath code into scenario as it affetcs readbility of code and hardens its support.</p>

<p>Lets see example of testing simple Yii 1.1 application page in Cest-way with <code class="language-plaintext highlighter-rouge">PhpBrowser</code> module:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>

<span class="kd">class</span> <span class="nc">IndexCest</span>
<span class="p">{</span>

  <span class="cd">/**
   * user name text field
   * @type string
   */</span>
  <span class="k">public</span> <span class="nv">$username</span> <span class="o">=</span> <span class="s1">'#LoginForm_username'</span><span class="p">;</span>

  <span class="cd">/**
   * user password text field
   * @type string
   */</span>
  <span class="k">public</span> <span class="nv">$password</span> <span class="o">=</span> <span class="s1">'#LoginForm_password'</span><span class="p">;</span>

  <span class="cd">/**
   * submit button
   * @type string
   */</span>
  <span class="k">public</span> <span class="nv">$enterButton</span> <span class="o">=</span> <span class="s1">'#login-form input[type=submit]'</span><span class="p">;</span>

  <span class="cd">/**
   *
   * @param \TestGuy $I
   * @param \Codeception\Scenario $scenario
   */</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">check_basic_login_logout</span><span class="p">(</span><span class="err">\</span><span class="nc">TestGuy</span> <span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'Test index page'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'My Web Application'</span><span class="p">,</span><span class="s1">'#header'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'login in the test app'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">username</span><span class="p">,</span><span class="s1">'demo'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">password</span><span class="p">,</span><span class="s1">'demo'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">enterButton</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeLink</span><span class="p">(</span><span class="s1">'Logout (demo)'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Logout (demo)'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeLink</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
  <span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see, it was easy to add move out selectors into UI properties if we are inside a calss.</p>

<p>Example of how to test CRUD operations with Selenium2 module is below. Please notice that all support methods are <code class="language-plaintext highlighter-rouge">protected</code>. They are called from test methods and won’t be executed as test themeselves.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="cd">/**
 * "Users" module CrudCest class file
 * @author Ragazzo
 */</span>

<span class="kd">class</span> <span class="nc">CrudCest</span>
<span class="p">{</span>

  <span class="cd">/**
   * your fields definitions goes 
   * here with UI-mappings
   * and other fields.
   *
   */</span>

  <span class="k">private</span> <span class="nv">$_userId</span><span class="p">;</span>

  <span class="cd">/**
   * new user created attributes
   */</span>
  <span class="k">private</span> <span class="nv">$_newAttrs</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'name'</span>  <span class="o">=&gt;</span> <span class="s1">'Ragazzo'</span><span class="p">,</span>
    <span class="s1">'email'</span> <span class="o">=&gt;</span> <span class="s1">'someRagazzoEmail@example.com'</span><span class="p">,</span>
    <span class="s1">'skype'</span> <span class="o">=&gt;</span> <span class="s1">'someRagazzoSkype'</span><span class="p">,</span>
  <span class="p">);</span>

  <span class="cd">/**
   * edited user attributes
   */</span>
  <span class="k">private</span> <span class="nv">$_editAttrs</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">'skype'</span> <span class="o">=&gt;</span> <span class="s1">'newRagazzoSkype'</span><span class="p">,</span>
  <span class="p">);</span>

  <span class="cd">/**
   *
   * @param \WebGuy $I
   * @param \Codeception\Scenario $scenario
   */</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">test_basic_users_module_crud</span><span class="p">(</span><span class="err">\</span><span class="nc">WebGuy</span> <span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create user and test basic crud in "Users" module'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">am</span><span class="p">(</span><span class="s1">'system root user'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">loginIntoTheSystem</span><span class="p">(</span><span class="s1">'somelogin'</span><span class="p">,</span><span class="s1">'somepassword'</span><span class="p">,</span><span class="nv">$I</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">create_new_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">update_created_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">delete_created_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="cd">/**
   *
   * @param \WebGuy $I
   * @param \Codeception\Scenario $scenario
   */</span>
  <span class="k">protected</span> <span class="k">function</span> <span class="n">create_new_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'create new user'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/users'</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Users'</span><span class="p">,</span><span class="s1">'.breadcrumbs'</span><span class="p">)</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Create'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Create'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInCurrentUrl</span><span class="p">(</span><span class="s1">'users/create'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Create'</span><span class="p">,</span><span class="s1">'.breadcrumbs'</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'submit form without required fields'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">saveButton</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expectTo</span><span class="p">(</span><span class="s1">'see required validation errors'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Name field can not be empty'</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'submit correctly filled form'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">email</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'email'</span><span class="p">]);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">skype</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'skype'</span><span class="p">]);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">saveButton</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expectTo</span><span class="p">(</span><span class="s1">'see correctly saved user info'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInCurrenturl</span><span class="p">(</span><span class="s1">'users/view'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'View'</span><span class="p">,</span><span class="s1">'.breadcrumbs'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Delete'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Edit'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeElement</span><span class="p">(</span><span class="s1">'.detail-view'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'name'</span><span class="p">],</span><span class="s1">'.detail-view'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'email'</span><span class="p">],</span><span class="s1">'.detail-view'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'skype'</span><span class="p">],</span><span class="s1">'.detail-view'</span><span class="p">);</span>

    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_userId</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabFromCurrentUri</span><span class="p">(</span><span class="s1">'~/id/(\d+)/~'</span><span class="p">);</span> 
  <span class="p">}</span>

  <span class="cd">/**
   *
   * @param \WebGuy $I
   * @param \Codeception\Scenario $scenario
   */</span>
  <span class="k">protected</span> <span class="k">function</span> <span class="n">update_created_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'change created user attributes'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">editUrl</span><span class="mf">.</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_userId</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">skype</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_editAttrs</span><span class="p">[</span><span class="s1">'skype'</span><span class="p">]);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">saveButton</span><span class="p">);</span>

    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expectTo</span><span class="p">(</span><span class="s1">'see that attributes has changed'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInField</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">skype</span><span class="p">,</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_editAttrs</span><span class="p">[</span><span class="s1">'skype'</span><span class="p">]);</span>
  <span class="p">}</span>

  <span class="cd">/**
   *
   * @param \WebGuy $I
   * @param \Codeception\Scenario $scenario
   */</span>
  <span class="k">protected</span> <span class="k">function</span> <span class="n">delete_created_user</span><span class="p">(</span><span class="nv">$I</span><span class="p">,</span> <span class="nv">$scenario</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/users'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'name'</span><span class="p">],</span><span class="s1">'#users-grid'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'name'</span><span class="p">],</span><span class="s1">'#users-grid'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Delete'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Delete'</span><span class="p">,</span><span class="s1">'.btn'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInCurrentUrl</span><span class="p">(</span><span class="s1">'/users'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">dontSee</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">_newAttrs</span><span class="p">[</span><span class="s1">'name'</span><span class="p">],</span><span class="s1">'#users-grid'</span><span class="p">);</span>
  <span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In this way you can use Cests classes for some tasks where it is difficult to use flat Cepts. You also can use Cests classes as PageObjects.</p>

<p>When you write tests with Codeception it is good to be verbose and use different methdos for that, so use them:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">$I-&gt;am</code> to say who you are and define your role;</li>
  <li><code class="language-plaintext highlighter-rouge">$I-&gt;wantTo</code> to say what feature you want to test;</li>
  <li><code class="language-plaintext highlighter-rouge">$I-&gt;amGoingTo</code> to say what you gonna do next;</li>
  <li><code class="language-plaintext highlighter-rouge">$I-&gt;expect</code> and <code class="language-plaintext highlighter-rouge">$I-&gt;expectTo</code> to say what do expect next to see in your test case as a user.</li>
</ul>

<p>Use this commands instead of comments in your tests. They will be displayed in scenario output and will provide you with additional information on steps taken.</p>

<p><em>We can say to Ragazzo for sharing his experience in using the Cest classes. Stil it might be a point of discussion, should a CRUD be tested in one test or in four. In both cases Cest classes are a good places to keep everything you need to test dealing with one entity. A user, in this case.</em></p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.6.1: Laravel and Groups</title>
      <link>https://codeception.com/05-08-2013/codeception-1-6-1-with-laravel-and-groups.html</link>
      <pubDate>Wed, 08 May 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-08-2013/codeception-1-6-1-with-laravel-and-groups</guid>
      <description><![CDATA[ <p>That was about a month of hard work on Codeception 1.6.1. Probably the hardest part was to provide more open architecture for testing framework. Right now it’s hard to customize anything in Codeception. We are going to fix that soon with new event system. We are going to release Extension (for hooking all the events) and Group classes (for events related to groups) in next release.</p>

<h3 id="hey-did-you-mention-groups">Hey, did you mention groups?</h3>

<p>Yep, you are right! From now on you can use group tests and execute them separately. 
You have a few ways to add test to a group. If it is a Cept scenario all of this methods will work.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">group</span><span class="p">(</span><span class="s1">'admin'</span><span class="p">);</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">group</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'admin'</span><span class="p">,</span><span class="s1">'critical'</span><span class="p">));</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">groups</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'admin'</span><span class="p">,</span><span class="s1">'critical'</span><span class="p">));</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="c1">// ...</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>For Cest and Test files you can use <code class="language-plaintext highlighter-rouge">@group</code> annotiation similarly as in PHPUnit:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
 <span class="cd">/**
  * @group model
  */</span> 
  <span class="k">public</span> <span class="k">function</span> <span class="n">testAdminIsCreated</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="c1">// test goes here</span>
  <span class="p">}</span>

<span class="cp">?&gt;</span></code></pre></figure>

<p>To execute tests of one group use:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php codecept.phar run -g admin
php codecept.phar run --group admin
</code></pre></div></div>

<p>To execute tests of several groups just pass multiple group options to runner.</p>

<h2 id="functional-tests-in-classes">Functional Tests in Classes</h2>

<p>As you know, we deprecated Cest format for unit testing and we propose you to use it for functional and acceptance tests. It should work well for you now. Soon we will publish a tutorial and guide for how to to this.
Basically you can generate a Cest file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php codecept.phar generate:cest acceptance MyCest
</code></pre></div></div>

<p>And write tests inside a newly created MyCest class.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">MyCest</span> 
<span class="p">{</span>
  <span class="k">public</span> <span class="k">function</span> <span class="n">loginPage</span><span class="p">(</span><span class="err">\</span><span class="nc">WebGuy</span> <span class="nv">$I</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">,</span> <span class="s1">'h1'</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">checkCopyrightIncluded</span><span class="p">(</span><span class="nv">$I</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">public</span> <span class="k">function</span> <span class="n">registrationPage</span><span class="p">(</span><span class="err">\</span><span class="nc">WebGuy</span> <span class="nv">$I</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/register'</span><span class="p">);</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Register'</span><span class="p">,</span> <span class="s1">'h1'</span><span class="p">);</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">checkCopyrightIncluded</span><span class="p">(</span><span class="nv">$I</span><span class="p">);</span>
  <span class="p">}</span>  

  <span class="k">protected</span> <span class="k">function</span> <span class="n">checkCopyrightIncluded</span><span class="p">(</span><span class="nv">$I</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'(c) 2013'</span><span class="p">,</span> <span class="s1">'#footer'</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>All public methods of Cest classes become tests. You can use private and prected methods and properties to share data and functionality over the tests. Also you can use setup/teardown preperations in <code class="language-plaintext highlighter-rouge">_before</code> and <code class="language-plaintext highlighter-rouge">_after</code> methods. If you want to make a bunch of simple tests and you don’t want to create a file for each - Cest is your choice. More docs on it coming.</p>

<h2 id="good-news-to-laravel-fans">Good news to Laravel fans</h2>

<p>Yes, yes. Finally we’ve got a module for <a href="https://codeception.com/docs/modules/Laravel4">Laravel4</a> framework functional testing. We couldn’t test it well, as there are not to much Laravel4 apps available on GitHub. But we run some basic tests on a CRUD app, and it worked nicely. Thanks to HttpFoundation component inside Laravel4 framework.</p>

<p>Larvael module is zero configuration. You should just bootstrap a project in your Laravel app directory and include <code class="language-plaintext highlighter-rouge">Laravel4</code> module into your functional test suite.</p>

<p>Take a look into <a href="https://github.com/Codeception/sample-l4-app">sample Laravel project</a> prepared my <strong>Jeffrey Way</strong> and <strong>Michael Bodnarchuk</strong> with sample test included.</p>

<h2 id="various-changes-and-fixes">Various changes and fixes.</h2>

<ul>
  <li>added <code class="language-plaintext highlighter-rouge">seeOptionIsSelected</code> methods for all modules that share FrameworkInterface.</li>
  <li>added <code class="language-plaintext highlighter-rouge">resizeWindow</code> method to Selenium2 module (thanks to Jaik Dean)</li>
  <li>Codeception is PHP 5.5 compatible. We learned that by launching tests on Travis (thanks to Tiger-Seo)</li>
  <li>fix for screenshots snapshot filenames in Cest files</li>
  <li>fix to <code class="language-plaintext highlighter-rouge">getStatusCode</code> method in frameworks tests</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Specification or Testing: The Comparison of Behat and Codeception</title>
      <link>https://codeception.com/05-06-2013/specification-testing-coparison.html</link>
      <pubDate>Mon, 06 May 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-06-2013/specification-testing-coparison</guid>
      <description><![CDATA[ <p><em>This is guest post by <a href="https://github.com/Ragazzo">Ragazzo</a>. He uses Behat as well as Codeception for making his project better. He was often asked to do a <strong>comparison between Codeception, Behat, and PhpUnit</strong>. In this post he explains the commons and different parts of this products.</em></p>

<p>In nowadays almost everyone knows how it is important to have stable and tested application. It is very difficult to create good application without involving different specific tools in your project. It is very important to develop your application through testing, according to TDD principle. There are different ways to write tests in PHP:</p>

<ul>
  <li>Classical unit-tests with PhpUnit;</li>
  <li>Functional (integration / end-to-end) tests with PhpUnit</li>
  <li>Functional web tests with Codeception / Behat+Mink</li>
  <li>Acceptance web tests with Codeception / Behat+Mink.</li>
</ul>

<h3 id="my-vision-of-bdd">My vision of BDD.</h3>

<p>Main difference between usual functional and acceptance tests is that in acceptance tests you can not manipulate directly with some “underground” application code. All you can do is just interact with things that was given to you by application. In functional tests you can interact with application internals, proceed some checks and conditions that can involve application parts not available for end-user.</p>

<p>If we are talking about “classical” functional tests also known as “end-to-end” or “integration” tests then simple example can be when you have to test some behavior of 2-3 components together, like logging, writing configs, etc. <strong>For functional tests (but not web) I prefer to use Behat</strong> by itself. And I have some reasons for that.</p>

<p><strong>Behavior Driven Development</strong>  helps you to start developing project from “how it must behave” and not from “what concrete components it must include in particular”.</p>

<p>It can be said that you write your thoughts about behavior of your application. And this helps you to build not simply a couple of classes powered by unit-tests, but an application with good design based on specific behavior. <strong>Behat</strong> is very powerful tool, but it has some common pitfalls that maybe looks weird to the user:</p>

<ul>
  <li>It could be said that it is a <strong>feature driven development</strong>. Thats why it is not so easy to use <em>subcontexts</em> in Behat. For example, if you have 30-40 tests it could be hard to maintain them, because of the same PhpDoc definitions for matching methods.</li>
  <li>If you use Behat+Mink for functional and acceptance tests, it also requires from you a good knowledge of  Mink’s internals to create your own methods to interact with a page.</li>
</ul>

<p>Lets see the example on how you can determine what components you need in your application in a “BDD” way.
Here we are creating dummy application for managing football clubs. Lets write some 2-3 scenarios in <strong>Gherkin</strong>:</p>

<figure class="highlight"><pre><code class="language-gherkin" data-lang="gherkin"><span class="c">#football_clubs.feature</span>

<span class="kd">Feature</span><span class="p">:</span> football_clubs
  As a football club owner
  I want to perform different actions with it.

  <span class="kn">Scenario</span><span class="p">:</span> transfer player to the club
    <span class="nf">Given </span>I have a football club <span class="s">"MyClub"</span>
    <span class="nf">Given </span>Football club budget is 100 mln. dollars
    <span class="nf">Given </span>Football player <span class="s">"GoodSkilledPlayer"</span> costs 35 mln. dollars
    <span class="nf">When </span>I try to buy this player
    <span class="nf">And </span>He see is available for transfer
    <span class="nf">Then </span>I sign player contract with 10 mln. dollars salary
    <span class="nf">And </span>I see player club is now <span class="s">"MyClub"</span>

  <span class="kn">Scenario</span><span class="p">:</span> get list of injured players
    <span class="nf">Given </span>I have a football club <span class="s">"MyClub"</span>
    <span class="nf">When </span>I get a list of injured players
    <span class="err">Then I see players in list</span><span class="p">:</span>
    <span class="s">"""
    FirstFootballPlayer
    SecondFootballPlayer
    """</span>
    <span class="err">And I dont see players in list</span><span class="p">:</span>
    <span class="s">"""
    ThirdFootballPlayer
    """</span></code></pre></figure>

<p>Thats all. We just wrote some thoughts on how an application should behave. From here we know what exactly we need: “Football Player” object, “Football Club” object, “Transfers Market” object. <strong>If you know how they must behave you do not need to think for hours on what unit-test you need to write, and whether they are really needed in the component behavior.</strong></p>

<p>Lets see another example of functional tests with Behat, for example we need to test config files of our system. Feature for that can be like this:</p>

<figure class="highlight"><pre><code class="language-gherkin" data-lang="gherkin"><span class="c">#config.feature</span>
<span class="kd">Feature</span><span class="p">:</span>
  In order to proceed config files for MyModule
  As a system root user i should be able
  to write correct info in files

  <span class="kn">Scenario</span><span class="p">:</span> write some users "context" info
  <span class="err">Given I have users in system</span><span class="p">:</span>
    <span class="p">|</span> <span class="nv">username</span> <span class="p">|</span> <span class="nv">email</span>              <span class="p">|</span>
    <span class="p">|</span> <span class="n">first</span>    <span class="p">|</span> <span class="n">first@example.com</span>  <span class="p">|</span>
    <span class="p">|</span> <span class="n">second</span>   <span class="p">|</span> <span class="n">second@example.com</span> <span class="p">|</span>
  <span class="nf">When </span>I dump users info to config file
  <span class="nf">Then </span>I should see
  <span class="s">"""
  #users
  username=first
  email=first@example.com

  username=second
  email=second@example.com
  """</span></code></pre></figure>

<p>As you see it is easy to read and also easy to understand. Thats why I prefer <code class="language-plaintext highlighter-rouge">Behat</code> for “classic” functional tests against usage of PhpUnit to test behavior of 2-3 components.</p>

<h2 id="ways-of-writing-acceptance-tests">Ways of Writing Acceptance Tests</h2>

<p>Now lets talk about functional and acceptance tests for web. Now we know difference between acceptance and functional tests, so in web tests difference is the same. There is a couple of tools to use for web functional and acceptance tests:</p>

<ul>
  <li>PhpUnit + Selenium</li>
  <li>Behat + Mink</li>
  <li>Codeception</li>
</ul>

<p><strong>I do prefer Codeception over Behat+Mink for web acceptance and functional tests</strong> for these reasons:</p>

<ul>
  <li>In web it is not very important to develop pages from how they need to behave. So there all power of Gherkin could not be applied. In this case Gherkin works just as simple translator and nothing more. My decision is to use right things for right purposes.</li>
  <li>As I’ve pointed out above you also need to know Mink “internals” (API) to proceed some your custom methods.</li>
  <li>Testing web-pages can lead to many <em>“Ambiguous”</em> or <em>“Redundant”</em> Behat feature steps.</li>
</ul>

<p>Of course there are some things to avoid this, but i prefer “easy-to-learn things” in this situation.</p>

<p>In that case Codeception offeres you a simple and very easy way to test your web application. Also I need to
notice that Codeception takes low-level Mink’s API and provides a high-level commands for end-user.</p>

<p>For example lets see simple <code class="language-plaintext highlighter-rouge">Codeception</code> Cept test case:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'Test index page'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/index.php'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'My Web Application'</span><span class="p">,</span><span class="s1">'#header #logo'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">,</span><span class="s1">'h1'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amGoingTo</span><span class="p">(</span><span class="s1">'login in the test app'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'#LoginForm_username'</span><span class="p">,</span><span class="s1">'demo'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'#LoginForm_password'</span><span class="p">,</span><span class="s1">'demo'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#login-form input[type="submit"]'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeLink</span><span class="p">(</span><span class="s1">'Logout (demo)'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Logout (demo)'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeLink</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you can see it is easy to read, and one really great thing is it is easy to write, because of auto-completion. In Behat when using Gherkin you can get some <em>“Undefined”</em> steps errors, just because you mistyped something. And it happens to be annoying.</p>

<p>Codeception bundled with modules for functional and acceptance tests: PhpBrowser (functional tests over curl), Selenium (1,2) for acceptance tests, etc. There are also some nice modules for REST, SOAP and XML-RPC that can help you to test your API.</p>

<p>It is need to be noticed that there are two types of web tests in Codeception: some require webserver and others not - all requests are processed directly by your applcation using Symfony’s BrowserKit Component.</p>

<p>Overall, my choice in Codeception is to use “PhpBrowser” module (requires a web-server) for headless web functional tests, and “Selenium2” module for complete web acceptance tests. Codeception also can generate BDD-style scenarios for you based on your Cepts.</p>

<p><strong>Also need to notice that maybe Codeception is not a “true” BDD, unlike Behat. Behat+Gherkin helps you to use and design your application. Codeception helps you to test it nicely.</strong></p>

<h3 id="links-to-read-and-get-more-info">Links to read and get more info</h3>

<ul>
  <li><a href="https://codeception.com">https://codeception.com</a></li>
  <li><a href="https://behat.org">https://behat.org</a></li>
  <li><a href="https://mink.behat.org/">https://mink.behat.org/</a></li>
  <li><a href="https://codeception.com/12-20-2012/not-bdd.html">Stop simulating BDD</a></li>
  <li><a href="https://phpmaster.com/ruling-the-swarm-of-tests-with-codeception/">Ruling the swarm of tests with Codeception</a></li>
</ul>

<p><em>This post was intended to be a start to series. In next posts you will learn how to use newcoming Cest format for testing and integrate Codeception with Continious integration tools. Stay tuned!</em></p>
 ]]></description>
    </item>
    
    <item>
      <title>The Platform (1.6.0): Interactive Console</title>
      <link>https://codeception.com/04-05-2013/codeception-platform-interactive-console.html</link>
      <pubDate>Fri, 05 Apr 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/04-05-2013/codeception-platform-interactive-console</guid>
      <description><![CDATA[ <p>Today we start new <strong>The Platform</strong> iteration. After 1.6 Codeception would become much more friendly and flexible in testing. Yet, no of announced features are introduced today. It’s really hard to keep promises especially if you come to idea of feature that would be really really helpful for acceptance testing.</p>

<h2 id="meet-interactive-console">Meet Interactive Console</h2>

<p>Within the interactive console you can try various commands without running a test.
It is quite useful when you deal with Selenium sessions for example. It always takes a long time to start and shutdown Selenium session. So it’s unpleasent to see that your test fails and it should checked saved and executed once again and once again.</p>

<p><img src="https://img267.imageshack.us/img267/204/003nk.png" alt="Interactive console" /></p>

<p>Interactive console should simplify writing tests as you can play with different selectors and commands.
Also it may be useful when you want to try your new RESTful API. In console you can execute Codeception commands as you use in tests, but receive immediate result.</p>

<p>Try using the console:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar console suitename</code></pre></figure>

<p>Every command is exuecuted with <code class="language-plaintext highlighter-rouge">eval</code>. So check a your input to be valid PHP. And yes, you can skip <code class="language-plaintext highlighter-rouge">$I-&gt;</code> in the begining and <code class="language-plaintext highlighter-rouge">;</code> in the end. But all the brackets and quites are required.</p>

<h2 id="low-level-apis">Low Level APIs</h2>

<p>Sometimes it happens that Codeception limits you in your actions. Probably you could solve the issue within a Selenium, but Codeception Modules may not provide full access to it. Well, before this day.</p>

<p>Now you can access launching backends directly in tests:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeInSelenium</span><span class="p">(</span><span class="k">function</span><span class="p">(</span><span class="err">\</span><span class="nc">WebDriver\Session</span> <span class="nv">$webdriver</span><span class="p">)</span> <span class="p">{</span>
   <span class="nv">$webdriver</span><span class="o">-&gt;</span><span class="nf">element</span><span class="p">(</span><span class="s1">'id'</span><span class="p">,</span><span class="s1">'link'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">''</span><span class="p">);</span>
<span class="p">});</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>For <strong>Selenium</strong>, <strong>Selenium2</strong> modules commands <code class="language-plaintext highlighter-rouge">executeInSelenium</code> were introduced. 
For <strong>PhpBrowser</strong> you can use <code class="language-plaintext highlighter-rouge">executeInGuzzle</code> which provides you access to Guzzle HTTP Client.</p>

<h2 id="zend-framework-2-initial-support">Zend Framework 2 Initial Support</h2>

<p>Thanks to <a href="https://github.com/bladeofsteel"><strong>bladeofsteel</strong></a> you can try to use Codeception with Zend Framework 2. Please try to use <strong>ZF2</strong> module on real Zend Framework 2 applications. ZF2 module is in <em>alpha</em> now, so your feedbacks, issues, and pull requests are highly appreciated.</p>

<h2 id="various-additions">Various additions</h2>

<ul>
  <li><code class="language-plaintext highlighter-rouge">defer-flush</code> option to <code class="language-plaintext highlighter-rouge">Run</code> was added by <strong>phpcodemonkey</strong>. It helps to overcome output errors for session in functional tests.</li>
  <li><code class="language-plaintext highlighter-rouge">amHttpAuthenticated</code> command added to all framework modules and PhpBrowser</li>
  <li>do not use steps option by default if it’s not a one test executed by <strong>tigerseo</strong></li>
  <li>fixes to AMQP module. Still it is in beta.</li>
  <li>you can use <code class="language-plaintext highlighter-rouge">Cest</code> files for writing functional and acceptance tests.</li>
  <li>CURL parameters can be set for PHPBrowser (SSL checks turned off by default).</li>
</ul>

<p>Sorry if some bugs were not fixed. Any help and pull requests are highly appreciated.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<p>Soon a new Guides will be added to documentation replacing the Scenario Unit Tests guides.
Follow the updates.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Update! Codeception 1.5.7 is out.</title>
      <link>https://codeception.com/03-24-2013/codeception-1-5-7.html</link>
      <pubDate>Sun, 24 Mar 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-24-2013/codeception-1-5-7</guid>
      <description><![CDATA[ <p>Great news. Codeception got attention from Nettuts community and we are happy to welcome you in the family ) 
What you should know about Codeception release cycle is that releases are not breaking the BCs and they appear quite often. Even minor releases introduces lots of new features. And today we’d like to announce some of them.</p>

<h3 id="more-current-url-methods">More Current Url Methods</h3>

<p>As were pointed, the <code class="language-plaintext highlighter-rouge">seeInCurrentUrl</code> method is not enough to test urls. So we got much more “currentUrl” methods:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// to match root url</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeCurrentUrlEquals</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeCurrentUrlMatches</span><span class="p">(</span><span class="s1">'~$/user/.*?~'</span><span class="p">)</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabFromCurrentUrl</span><span class="p">();</span>
<span class="nv">$user_id</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabFromCurrentUrl</span><span class="p">(</span><span class="s1">'~/user/(\d+)~'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And yes, we have correspoinding <code class="language-plaintext highlighter-rouge">dontSee</code> methods too.</p>

<h3 id="click-on-context">Click on context</h3>

<p>Now you can perform clicks in context elements:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">,</span> <span class="s1">'#nav'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">,</span> <span class="s1">'//html/body/div/a'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Also you can now try to use Cest classes for acceptance and functional testing. As scenario-driven unit tests are going to be deprecated, Cests will be used as Cepts, but in a format of a class. The Cest generator was updated accrodingly.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li>Yii module should work as expected as all reauired files are included in package.</li>
  <li>Fix to Kohana module.</li>
  <li><code class="language-plaintext highlighter-rouge">$scenario-&gt;preload()</code> is back</li>
</ul>

<h3 id="announcing-the-platform">Announcing: The Platform</h3>

<p>Next major release will be called <strong>The Platform</strong>. In Platform we will introduce lots of a new concepts designed to build a real test automation platform.</p>

<ul>
  <li>Extensions - classes that can hook into any events and produce their own. Extend anything.</li>
  <li>Tags - unite tests into groups and provide a similar hooks for them.</li>
  <li>Conditional Asserts - don’t stop a test if assert fails.</li>
  <li>PageObjects - new classes for defining UI maps.</li>
  <li>Controllers - classes to define similar scenario logic.</li>
  <li>Multiple Sessions - ability to execute same tests with different config (i.e. inside chrome then firefox)</li>
</ul>

<p>More about <a href="https://phpmaster.com/ruling-the-swarm-of-tests-with-codeception/">PageObjects and Controllers you can read on PHPMaster</a>.</p>

<h3 id="help-from-community">Help from Community</h3>

<p>And we’d like to ask you for help (once again). <strong>Please <a href="https://surveymonkey.com/s/982RCG9">pass this survey</a></strong>. 
We develop a bugtracker <a href="https://bugira.com">Bugira</a> specially for web developments. And to get it running we need your feedback.</p>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<p>P.S. It’s only 3 minutes of your time: <a href="https://surveymonkey.com/s/982RCG9">pass this survey</a>. Thanks</p>
 ]]></description>
    </item>
    
    <item>
      <title>Scenario Unit Tests Deprecation Announcement</title>
      <link>https://codeception.com/03-18-2013/scenario-unit-deprecated.html</link>
      <pubDate>Mon, 18 Mar 2013 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-18-2013/scenario-unit-deprecated</guid>
      <description><![CDATA[ <p>We decided to get rid of the scenario unit tests. The main reason is: the concept was interesting, but current realization is a bit outdated. 
It would take to much time to maintain and support them. Hopefully, not to much developers used them anyway ) They are cool if you are dealing with mocks in your tests, but they don’t bring any value if you write a plain unit test. We’ve seen too much improperly written unit tests in Cest format so we’d actually recommend you to switch to classical unittests with codeGuy helpers.</p>

<p>So now recommended are Codeception driven unit tests, in PHPUnit like format:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">UserTest</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\TestCase\Test</span> <span class="p">{</span>

  <span class="k">function</span> <span class="n">_before</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">User</span><span class="p">();</span>
  <span class="p">}</span>


  <span class="k">function</span> <span class="n">testUserIsSaved</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="s1">'miles'</span><span class="p">;</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user</span><span class="o">-&gt;</span><span class="nf">save</span><span class="p">();</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">codeGuy</span><span class="o">-&gt;</span><span class="nf">seeInDatabase</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'miles'</span><span class="p">));</span>
  <span class="p">}</span>  
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>If you still interested in scenario driven tests, leave your feedback or even propose your concept. <a href="https://gist.github.com/DavertMik/5042537">Here is one of them</a>
The real idea behind scenario driven unit tests to have code well described in a human language. This is especially useful when dealing with mocks and stubs. In this case we can implement some ‘magic’ methods that allows us to simplify manipulation with code and write only definitions. What methods do we need, what methods do we test, what we expect to see. No unnescessary technlical details. Only logic and dependencies.</p>

<p>The Cest format itself is not going to be deprecated. It would be proposed to use in functional or acceptance tests as an alternative. If you like to write tests in a class (rather then plain PHP file), please use Cest format. More announcement comes on this soon. Expect a new vewsion.</p>

<p>Scenario driven tests <strong>will be removed in 1.7 version</strong> of Codeception.
So migrate them to regular unit tests.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.5.6</title>
      <link>https://codeception.com/03-10-2013/codeception-1-5-6.html</link>
      <pubDate>Sun, 10 Mar 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/03-10-2013/codeception-1-5-6</guid>
      <description><![CDATA[ <p>Codeption 1.5.6 released with varous fixes to Selenium2 module (popups, screenshots) an other bugfixes.
We added a bunch of tests for Selenium2 and they are runnng on TravisCI. 
Also, Codeception is now compatble with Symony 2.2. And few features were intrduced.</p>

<h3 id="basic-fixtures">Basic Fixtures</h3>

<p>Very basic implementation of fixtures was added to Db and Mongo modules.
Now you can write something like:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// for Db</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveInDatabase</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="c1">// for Mongo</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveInCollection</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>to add data for a test. For Db module, the inserted record will be cleaned up on text test, even If <code class="language-plaintext highlighter-rouge">cleanup</code> option is set to false. So <code class="language-plaintext highlighter-rouge">haveInDatabase</code> method cleans data after itself.
Something similar exists for Doctrine2 module. Yet, it looks not like for Db and Mongo implementation:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">persistEntity</span><span class="p">(</span><span class="k">new</span> <span class="err">\</span><span class="nc">Entity\User</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'Miles'</span><span class="p">));</span></code></pre></figure>

<h3 id="error-handling">Error Handling</h3>

<p>From now on you can set custom error handling parameters per suite or globally.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">WebGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">PhpBrowser</span><span class="pi">,</span> <span class="nv">WebHelper</span><span class="pi">]</span>
<span class="na">error_level</span><span class="pi">:</span> <span class="s2">"</span><span class="s">E_ALL</span><span class="nv"> </span><span class="s">&amp;</span><span class="nv"> </span><span class="s">~E_STRICT</span><span class="nv"> </span><span class="s">&amp;</span><span class="nv"> </span><span class="s">~E_DEPRECATED"</span></code></pre></figure>

<p>Actually, <code class="language-plaintext highlighter-rouge">E_ALL &amp; ~E_STRICT &amp; ~E_DEPRECATED</code> is default error level for now. This may be changed in future.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li>popups and modals in Selenium2 are fully tested and work correctly now</li>
  <li>screenshots in Selenium2 module is saved correctly</li>
  <li><code class="language-plaintext highlighter-rouge">seeInField</code> method works correctly even if field is not in form</li>
  <li>fix to AMQP module to push message to queue</li>
  <li>Symfony 2.2 compatibility</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.5.5 and Roadmap Announced</title>
      <link>https://codeception.com/02-28-2013/codeception-1-5-5-roadmap.html</link>
      <pubDate>Thu, 28 Feb 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-28-2013/codeception-1-5-5-roadmap</guid>
      <description><![CDATA[ <p>Yes, here is a new version of Codception with more features and bugfixes in it.
We have a flexible relase cycle, so the new version comes when we have a set of updates that you might be needed.
We want to say “thank you” for all contributors, and for everyone who helps making Codeption better. 
It’s always nice to get pull requests or <a href="https://github.com/Codeception/Codeception/issues/">follow discussions</a> in our issues secition.
So let us sum up the work was done during last 2 weeks and share it with you.</p>

<h3 id="use-codeception-in-different-places">Use Codeception in Different Places</h3>

<p>All codeception commands got <code class="language-plaintext highlighter-rouge">-c</code> option to provide a custom path to tests.
The exception is <code class="language-plaintext highlighter-rouge">bootstrap</code> command. It accepts a custom directory as a second argument:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar bootstrap ~/mynewproject
php codecept.phar generate:cept acceptance Login <span class="nt">-c</span> ~/mynewproject
php codecept.phar generate:test unit MyFirstTest <span class="nt">-c</span> ~/mynewproject
php codecept.phar run <span class="nt">-c</span> ~/mynewproject
php codecept.phar generate:scenarios acceptance <span class="nt">-c</span> ~/mynewproject</code></pre></figure>

<p>Alternatively you may specify path to <code class="language-plaintext highlighter-rouge">codeception.yml</code> file in <code class="language-plaintext highlighter-rouge">-c</code> option: <code class="language-plaintext highlighter-rouge">php codecept.phar run -c ~/mynewproject/codeception.yml</code></p>

<p>Thus, you don’t need to keep your <code class="language-plaintext highlighter-rouge">codecept.phar</code> in the root of your project anymore. Use <code class="language-plaintext highlighter-rouge">-c</code> option and one local runner for all your projects.</p>

<h3 id="skipping-tests">Skipping Tests</h3>

<p>Skipping and marking tests of incomplete was improved. We did a new solid implementation for it (it was very basic in <code class="language-plaintext highlighter-rouge">1.5.4</code>).
Now If a test is marked to skip, no modules will be touched.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">skip</span><span class="p">(</span><span class="s1">'this is not ready yet, move along'</span><span class="p">);</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wanTo</span><span class="p">(</span><span class="s1">'do something, but I would rather not'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="c1">//.....</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This feature required to rework some core classes (like Step and TestCase and Scenario) but hopefully we simplified our code.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">acceptPopup</code> with Selenium 2 does not trigger Exception any more</li>
  <li>error handling was improved to skip blocked with <code class="language-plaintext highlighter-rouge">@</code> alerts, yet to throw <code class="language-plaintext highlighter-rouge">ErrorException</code> for notices, warnings, errors.</li>
  <li>ZombieJS configuration was fixed. Now the <code class="language-plaintext highlighter-rouge">url</code> parameter is required to specify app’s local url.</li>
  <li>REST <code class="language-plaintext highlighter-rouge">seeStatusCodeIs</code> method works correctly with Symfony2 now.</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<h2 id="roadmap">Roadmap</h2>

<p>For the first time we will announce the roadmap for Codeception. Actually we need your opinion: what features you’d like to see in new releases, and what things can be postponed. The list below is not a precise plan, but just a list of features we have in mind:</p>

<ul>
  <li>Make a PageObject pattern first-class citizen in Codeception. Add generators and guides to use PageObjects (for acceptance tests).</li>
  <li>Multiple sessions for tests execution (<a href="https://github.com/Codeception/Codeception/issues/154">see discission on GitHub</a>)</li>
  <li><strong>Silex</strong>, <strong>Laravel 4</strong>, <strong>Zend Framework 2</strong>, <strong>Drupal 8</strong>, <strong>Phalcon</strong> integrations. The key problem here: we can’t do this on our own. We need a real users of these frameworks, to create integration and test it on their projects. We have reworked <a href="https://codeception.com/docs/05-FunctionalTests">functional testing guide</a> to help you with this. Also use GitHub or personal contacts if you want to make a module.</li>
  <li><strong>Scenario Unit Tests to be rethinked</strong>. We have 2 options here: dump scenario driven unit tests (or mark them as deprecated) or rework them. Actually we need your real opinion. <a href="https://gist.github.com/DavertMik/5042537">Here is an example of what new Cests may look like</a>. They will dramatically improve the way you work with mocks and stubs in PHP. But will you use it? Please, let us know what you think.</li>
</ul>

<p>To summarize: we’d appreciate contributions, feedbacks and ideas for next releases.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.5.4. Skip Tests, UTF fixes, etc.</title>
      <link>https://codeception.com/02-15-2013/codeception-1-5-4.html</link>
      <pubDate>Fri, 15 Feb 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-15-2013/codeception-1-5-4</guid>
      <description><![CDATA[ <p>Today we are releasing Codeception 1.5.4. This is minor bugfixing release consisting of GitHub issues. 
And a small yet awaitied feature introduced: ability to skip and mark Cepts as incomplete.</p>

<p>It’s pretty simple, though.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">skip</span><span class="p">();</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wanTo</span><span class="p">(</span><span class="s1">'do something, but I would rather not'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="c1">//.....</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This makes this test to be skipped.
Similarly it can be marked as incomplete.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">incomplete</span><span class="p">();</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wanTo</span><span class="p">(</span><span class="s1">'do something, but I would rather not'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="c1">//.....</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The <code class="language-plaintext highlighter-rouge">skip</code> and <code class="language-plaintext highlighter-rouge">incomplete</code> methods can take one argument, that descrines a reason why this tests were marked this way.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">skip</span><span class="p">(</span><span class="s1">'waiting for new markup'</span><span class="p">);</span>
<span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">incomplete</span><span class="p">(</span><span class="s1">'welcome page appearence not tested'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>Symfony2 kernel is rebooted on each run. That make Symfony2 tests less dependent on each other.</li>
  <li><code class="language-plaintext highlighter-rouge">seeFillField</code> method now <a href="https://github.com/Codeception/Codeception/issues/162">accepts label as parameter</a>.</li>
  <li><a href="https://github.com/Codeception/Codeception/issues/120">Encoding issues</a> for non-latin chars in output fixed. Unfortunately this fix will work only in PHP 5.4.</li>
  <li><code class="language-plaintext highlighter-rouge">seeLink</code> now doesn’t <a href="https://github.com/Codeception/Codeception/issues/90">return false positive results</a></li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Testing Symfony2 Apps with Codeception</title>
      <link>https://codeception.com/02-12-2013/testing-symfony2.html</link>
      <pubDate>Tue, 12 Feb 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-12-2013/testing-symfony2</guid>
      <description><![CDATA[ <p>From the beginning of it’s existence Codeception was in good relations with Symfony2 framework. Codeception was built on Symfony Components and uses BrowserKit and HttpKernel components for launching functional tests. It’s a shame we didn’t have a complete Symfony2 integration tutorial before. But we will try to fill this gap today.</p>

<p>What benefits you get by using Codeception with Symfony2?
Let’s list all of them:</p>

<ul>
  <li>user-friendly syntax for functional tests</li>
  <li>access to container in unit tests</li>
  <li>testing REST and SOAP services built on Symfony</li>
  <li>fastest data cleanup when using with Doctrine2</li>
</ul>

<p>The installation is pretty simple. You can use <a href="https://codeception.com/install">Composer</a> (as you are used to it), but we’d recommend to try <a href="https://codeception.com/thanks">phar package</a>. In this case you can avoid unnecessary dependencies. But all this versions are equal. And when you installed Codeception and executed a <code class="language-plaintext highlighter-rouge">bootstrap</code> command you should configure your functional test suite.</p>

<p>In file <code class="language-plaintext highlighter-rouge">tests/functional.suite.yml</code>:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">TestGuy</span>
<span class="na">modules</span><span class="pi">:</span>
    <span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Symfony2</span><span class="pi">,</span> <span class="nv">Doctrine2</span><span class="pi">,</span> <span class="nv">TestHelper</span><span class="pi">]</span></code></pre></figure>

<p>And nothing more. You just need to declare that you will be using Symfony2 and Doctrine2. The Symfony2 module will search for <code class="language-plaintext highlighter-rouge">AppKrenel</code> on initialization (in <code class="language-plaintext highlighter-rouge">app</code>) and use it for functional tests. Doctrine2 module will find that Symfony2 module is declared and will try to receive default database connection from container. Of course, If you use non-standard setup this behavior can be reconfigured.</p>

<h2 id="functional-testing">Functional Testing</h2>

<p>Let’s create a first functional test. We use <code class="language-plaintext highlighter-rouge">generate:cept functional TestName</code> command.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'log in to site'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'username'</span><span class="p">,</span> <span class="s1">'admin'</span><span class="p">);</span>
<span class="c1">// ....</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And so on. Unlike standard Symfony2 tests you don’t need to deal with filters, CSS, and XPaths. Well, you can use CSS or XPath in any selector, if you need to. But on start you can keep your test simple and compact.</p>

<p>The commands we use here are common for most modules that perform testing of web application. That means, that once you discover a need for Selenium, this test can be executed inside a web browser using Selenium2 module. But some commands are unique to Symfony2 module. For example, you can use <code class="language-plaintext highlighter-rouge">seeEmailIsSent</code> command that checks if application has submitted an email during the last request. Check <a href="https://codeception.com/docs/modules/Symfony2">Symfony2</a> module reference for all commands we provide.</p>

<h2 id="unit-testing">Unit Testing</h2>

<p>Codeception’s unit tests are a bit improved PHPUnit’s tests. Inside a unit tests you have access to initialized modules and guy classes.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">PaginateTest</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\TestCase\Test</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="nv">$serviceContainer</span><span class="p">;</span>
    <span class="k">protected</span> <span class="nv">$codeGuy</span><span class="p">;</span>

    <span class="k">protected</span> <span class="k">function</span> <span class="n">_before</span><span class="p">()</span>
    <span class="p">{</span>
    	<span class="c1">// accessing container</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">serviceContainer</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'Symfony2'</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">container</span><span class="p">;</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">serviceContainer</span><span class="o">-&gt;</span><span class="nf">enterScope</span><span class="p">(</span><span class="s1">'request'</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testDefaults</span><span class="p">()</span>
    <span class="p">{</span>
    	<span class="c1">// using container</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">serviceContainer</span><span class="o">-&gt;</span><span class="nf">set</span><span class="p">(</span><span class="s1">'request'</span><span class="p">,</span> <span class="k">new</span> <span class="nc">Request</span><span class="p">(),</span> <span class="s1">'request'</span><span class="p">);</span>
        <span class="nv">$paginate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Paginate</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'Symfony2'</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">container</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nv">$paginate</span><span class="o">-&gt;</span><span class="nf">getCurrentPage</span><span class="p">());</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$paginate</span><span class="o">-&gt;</span><span class="nf">getCount</span><span class="p">());</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertEquals</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="nv">$paginate</span><span class="o">-&gt;</span><span class="nf">getLimit</span><span class="p">());</span>

        <span class="c1">// checking data in repository</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">codeGuy</span><span class="o">-&gt;</span><span class="nf">seeInRepository</span><span class="p">(</span><span class="s1">'SettingsBundle:Settings'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'pager_limit'</span> <span class="o">=&gt;</span> <span class="mi">20</span><span class="p">]);</span>
    <span class="p">}</span>
<span class="p">}</span>    
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>If you want to bypass Codeception hooks for PHPUnit you can create a plain PHPUnit test with <code class="language-plaintext highlighter-rouge">generate:phpunit</code> command and get a traiditional PHPUnit’s test. 
Then you can put this test into bundle.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Ok, you will probably ask: why is it better then Behat. We have a <a href="https://codeception.com/12-20-2012/not-bdd.html">wide answer for that</a>. A short is: Codeception is for testing, Behat is for Behavior Driven Development. If you need a professional testing tool that supports <a href="https://codeception.com/10-30-2012/pro-tips-1.html">PageObject</a> pattern, complex <a href="https://codeception.com/09-24-2012/locator.html">Locators</a>, refactoring capabilities and <a href="https://codeception.com/docs/11-Codecoverage">CodeCoverage</a> - Codeception is a good choice for that.</p>

<p>We say thanks to @everzet for wonderful Mink (that is used for acceptance tests) and to Sebastian Bergmann for it’s PHPUnit. Codeception uses their powers, but makes them a bit simpler in use.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.5.3</title>
      <link>https://codeception.com/02-08-2013/codeception-1-5-3.html</link>
      <pubDate>Fri, 08 Feb 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-08-2013/codeception-1-5-3</guid>
      <description><![CDATA[ <p><strong>Urgent fix for Selenium2 module</strong>. It appeared that <a href="https://github.com/Codeception/Codeception/issues/112">Selenium sessions were not restarting</a>. The Travis-CI didn’t reveal this problem. Selenium tests were passing as usual, just because there were no session related tasks. Main purpose for 1.5.3 was to release this fix. Some other fixes are also included, but it’s the most important one.</p>

<h3 id="modules">Modules</h3>

<p>In this release we also introduce very basic implementation of <strong>Yii</strong> module by <a href="https://github.com/Ragazzo">Ragazzo</a>. If you use <strong>Yii</strong>, please try it and help us improve Yii integration. To start using, please review the <a href="https://codeception.com/docs/modules/Yii1">module documentation</a> and <a href="https://github.com/Codeception/Codeception/pull/115">issue description</a> on Github.</p>

<p>Also we’ve got some improvements for <a href="/docs/modules/AMQP">AMQP</a> module. Not only queues are cleaned up between tests, but also you can check if messages came to queue, grab them from queues, or publish new messages. This module was tested with RabbitMQ, but it should work with other AMQP providers too. This module is based on <a href="https://github.com/videlalvaro/php-amqplib">php-amqplib</a>.</p>

<h3 id="generators">Generators</h3>

<p>From now on you can generate classical PHPUnit tests, with no Codeception stuff in it. Just the plain old PHPUnit tests that you can run natively with PHPUnit itself.
For this we have new command <code class="language-plaintext highlighter-rouge">generate:phpunit</code></p>

<p>Use it as regular:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar generate:phpunit NewTest</code></pre></figure>

<p>Also generators now support namespaces. So when you type class name with namespaced, Codeception will generate directories (according to PSR-0) and will put <code class="language-plaintext highlighter-rouge">namespace</code> into your newly generated file.</p>

<p>Check out sample usages.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar generate:cest <span class="se">\\</span>Entity<span class="se">\\</span>User
php codecept.phar generate:test <span class="se">\\</span>Entity<span class="se">\\</span>User
php codecept.phar generate:phpunit unit <span class="se">\E</span>ntity<span class="se">\\</span>User
php codecept.phar generate:phpunit unit <span class="s2">"</span><span class="se">\E</span><span class="s2">ntity</span><span class="se">\U</span><span class="s2">ser"</span></code></pre></figure>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Connecting PHP Frameworks. Part 1</title>
      <link>https://codeception.com/01-24-2013/connecting-php-frameworks-1.html</link>
      <pubDate>Thu, 24 Jan 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-24-2013/connecting-php-frameworks-1</guid>
      <description><![CDATA[ <p>As you know, Codeception has various modules for functional testing of PHP applications. Really, you could use Selenium, but as an advice, please leave Selenium for QAs.</p>

<p>As a developer you need to get more technical details for each test. If test fails you need to see the actual stack trace. As a developer you need to have all test running much faster. You can’t wait for an hour before pushing your commit.</p>

<p>If you ever had tried Codeception with Symfony2 you should know how fast are functional tests. You should know how helpful is printed information from profiler: queries used, user authentication status, etc.</p>

<p>In case you want to try functional tests with your own framework you should develop module for it. Basically it’s not that hard as you think it is. But some frameworks suit better for integrations and some need additional hooks. In this post I will concentrate on integrating one of the modern PHP frameworks that use <strong>HttpKernel</strong> Symfony Component.</p>

<p>There are <strong>Laravel 4</strong> and <strong>Drupal 8</strong> that adopted HttpKernel interface. And more frameworks to come…</p>

<p>So in case you want to integrate Laravel or Drupal, or you know that your framework uses HttpKernel, you should follow this guide.</p>

<p>If you are not aware of what HttpKernel class is, please follow <strong>Fabien Potencier</strong>’s’ series of posts <a href="https://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1">Create your own framework… on top of the Symfony2 Components</a></p>

<h3 id="contributors-notice">Contributor’s Notice</h3>

<p>First of all, how do we treat the user contributions? In Codeception we have liberal politics for accepting pull requests. The only thing, we can’t test your implementation, as we just don’t have experience in this frameworks. So when you commit module please test your module, and prepare to be it’s maintainer. So you will need to write proper documentation and provide support it. Answer to questions on GitHub, in Twitter, etc. Yep, this is opensource.</p>

<p>But we will help you with that. The more developers will use your framework the more contributions your module will receive. So try to encourage framework community to test your module, use it and improve.</p>

<p>When your module is complete it will be packaged with Codeception and it’s reference will be published on this site. This is done to make Codeception with all it’s modules work out of the box from one phar archive.</p>

<h3 id="technical-implementation">Technical Implementation</h3>

<p>So you decided to create a module for Codeception that provides integration with <strong>HttpKernel</strong>. Hope you do!</p>

<p>Check how it is done for <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Module/Symfony2.php">Symfony2</a></p>

<ol>
  <li>We load and initialize HttpKernel class in <code class="language-plaintext highlighter-rouge">_initialize</code> method.</li>
  <li>Before each test we create a <strong>HttpKernel\Client</strong> class for this kernel in <code class="language-plaintext highlighter-rouge">_before</code> method</li>
  <li>We shut down client after each test in <code class="language-plaintext highlighter-rouge">_after</code> method.</li>
</ol>

<p>Let’s narrow it to example.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">Codeception\Module</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Symfony\Component\HttpKernel\Client</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">MyFrameworkModule</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Util\Framework</span> <span class="p">{</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="c1">// $app implements HttpKernelInterface</span>
		<span class="nv">$app</span> <span class="o">=</span> <span class="k">require_once</span> <span class="err">\</span><span class="nc">Codeception\Configuration</span><span class="o">::</span><span class="nf">projectDir</span><span class="p">()</span><span class="mf">.</span><span class="s1">'/app.php'</span><span class="p">;</span>
		<span class="nv">$app</span><span class="o">-&gt;</span><span class="nf">setEnvironment</span><span class="p">(</span><span class="s1">'test'</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span> <span class="o">=</span> <span class="nv">$app</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">_before</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\TestCase</span> <span class="nv">$test</span><span class="p">)</span>
	<span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Client</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">client</span><span class="o">-&gt;</span><span class="nf">followRedirects</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
	<span class="p">}</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">_after</span><span class="p">(</span><span class="err">\</span><span class="nc">Codeception\TestCase</span> <span class="nv">$test</span><span class="p">)</span>
	<span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">shutdown</span><span class="p">();</span>		
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And basically that’s all you need for integration. The Client class has everything to simulate requests and parse responses. Every module that extends <code class="language-plaintext highlighter-rouge">Codeception\Util\Framework</code> class will have actions: <code class="language-plaintext highlighter-rouge">click</code>, <code class="language-plaintext highlighter-rouge">see</code>, <code class="language-plaintext highlighter-rouge">fillField</code>, defined and documented in <code class="language-plaintext highlighter-rouge">Codeception\Util\FrameworkInterface</code>. This actions will work in just the same manner as for other frameworks. And it’s really cool, that testing client is not aware of framework it is testing. All methods and their behavior are just the same. So tests for Symfony2, Zend, or your newly integrated frameworks will look just the same.</p>

<p>Still you may want to add something special for your framework. Maybe some additional initialization steps, or new actions. Let’s say a framework you integrate have methods to authenticate a user by name. Why not to use this ability and to make a short cut for logging in?</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">namespace</span> <span class="nn">Codeception\Module</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Symfony\Component\EventDispatcher\EventDispatcher</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">Symfony\Component\HttpKernel\Client</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">MyFrameworkModule</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Util\Framework</span> <span class="p">{</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="c1">// $app implements HttpKernelInterface</span>
		<span class="nv">$app</span> <span class="o">=</span> <span class="k">require_once</span> <span class="nc">Codeception\Configuration</span><span class="o">::</span><span class="nf">projectDir</span><span class="p">()</span><span class="mf">.</span><span class="s1">'/app.php'</span><span class="p">;</span>
		<span class="nv">$app</span><span class="o">-&gt;</span><span class="nf">setEnvironment</span><span class="p">(</span><span class="s1">'test'</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span> <span class="o">=</span> <span class="nv">$app</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">amLoggedAs</span><span class="p">(</span><span class="nv">$username</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">getService</span><span class="p">(</span><span class="s1">'session'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">authenticate</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>

		<span class="nv">$role</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">getService</span><span class="p">(</span><span class="s1">'session'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">getRole</span><span class="p">();</span>
		<span class="nv">$permission</span> <span class="o">=</span> <span class="nv">$$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">getService</span><span class="p">(</span><span class="s1">'session'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">getPermissions</span><span class="p">();</span>

		<span class="c1">// let's display additional information</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">debugSection</span><span class="p">(</span><span class="s1">'Role'</span><span class="p">,</span> <span class="nv">$role</span><span class="p">);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">debugSection</span><span class="p">(</span><span class="s1">'Permissions'</span><span class="p">,</span> <span class="nb">json_encode</span><span class="p">(</span><span class="nv">$permission</span><span class="p">));</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>So now we can write a test like this:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amLoggedAs</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/user/profile'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Davert'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see, framework integration allows us to access it’s internals. Services, classes, configurations, etc. Please add methods that you think may be useful for other developers that will write functional tests.
Also you can display some technical details with <code class="language-plaintext highlighter-rouge">debug</code> and <code class="language-plaintext highlighter-rouge">debugSection</code> methods.</p>

<p>Let other modules get access to framework internals too. In our case we can define <code class="language-plaintext highlighter-rouge">kernel</code> as public property and make it accessible from user helper classes.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">MyFrameworkModule</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Util\Framework</span> <span class="p">{</span>
	<span class="k">public</span> <span class="nv">$kernel</span><span class="p">;</span>
<span class="p">}</span>	
<span class="cp">?&gt;</span></code></pre></figure>

<p>In helper:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span> 
<span class="kd">class</span> <span class="nc">TestHelper</span> <span class="kd">extends</span> <span class="nc">Codeception\Module</span> <span class="p">{</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">doSomeTrickyStuff</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$kernel</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'MyFrameworkModule'</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="p">;</span>
		<span class="nv">$kernel</span><span class="o">-&gt;</span><span class="nf">doTrickyStuff</span><span class="p">();</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In case you want to provide flexibility you can add configurable parameters to your module.
Let’s update our example to use additional parameters.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">MyFrameworkModule</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Util\Framework</span> <span class="p">{</span>
	
	<span class="c1">// paramter with default var</span>
	<span class="k">protected</span> <span class="nv">$config</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">'file_name'</span> <span class="o">=&gt;</span> <span class="s1">'app.php'</span><span class="p">);</span>

	<span class="c1">// a parameter that we can't guess	</span>
	<span class="k">protected</span> <span class="nv">$requiredFields</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">'app_name'</span><span class="p">);</span>

	<span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="c1">// $app implements HttpKernelInterface</span>
		<span class="nv">$app</span> <span class="o">=</span> <span class="k">require_once</span> <span class="nc">Codeception\Configuration</span><span class="o">::</span><span class="nf">projectDir</span><span class="p">()</span><span class="mf">.</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">config</span><span class="p">[</span><span class="s1">'file_name'</span><span class="p">];</span>
		<span class="nv">$app</span><span class="o">-&gt;</span><span class="nf">setEnvironment</span><span class="p">(</span><span class="s1">'test'</span><span class="p">);</span>
		<span class="nv">$app</span><span class="o">-&gt;</span><span class="nf">init</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">config</span><span class="p">[</span><span class="s1">'app_name'</span><span class="p">]);</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span> <span class="o">=</span> <span class="nv">$app</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span>	
<span class="cp">?&gt;</span></code></pre></figure>

<p>Module won’t start if <code class="language-plaintext highlighter-rouge">app_name</code> parameter is not set. But <code class="language-plaintext highlighter-rouge">file_name</code> parameter is optional and can be redefined.</p>

<p>In the end here how should look <code class="language-plaintext highlighter-rouge">functional.suite.yml</code> that includes your newly developed module:</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">TestGuy</span>
<span class="na">modules</span><span class="pi">:</span>
<span class="err">	</span><span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">MyFrameworkModule</span><span class="pi">,</span> <span class="nv">TestHelper</span><span class="pi">]</span>
<span class="err">	</span><span class="na">config</span><span class="pi">:</span>
<span class="err">		</span><span class="na">MyFrameworkModule</span><span class="pi">:</span>
<span class="err">			</span><span class="na">app_name</span><span class="pi">:</span> <span class="s">blog</span></code></pre></figure>

<p>Keep in mind that main principles of all Codeception modules are simple and smart. 
This means, if you can guess some parameters - do not require them to be explicitly set.</p>

<h2 id="conclusion">Conclusion</h2>

<p>It’s pretty simple to integrate any framework if it’s modern and built with Symfony Components. 
If you have various projects using this framework and you want to get it tested well, try to develop integration. It’s not that hard: only 3 methods to implement. Share your work with others, and let it be added to main package.</p>

<p>We appreciate all contributions and all frameworks. Let’s unite the PHP world!</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codecepion 1.5.2</title>
      <link>https://codeception.com/01-21-2013/codeception-1-5-2.html</link>
      <pubDate>Mon, 21 Jan 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-21-2013/codeception-1-5-2</guid>
      <description><![CDATA[ <p>Yet another minor release. It introduces more compact form for unit tests.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="nc">Codeception\Util\Stub</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">UserRepositoryTest</span> <span class="kd">extends</span> <span class="nc">Codeception\TestCase\Test</span>
<span class="p">{</span>
    <span class="k">protected</span> <span class="k">function</span> <span class="n">_before</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">User</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">testUserIsNotAdmin</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertFalse</span><span class="p">(</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">isAdmin</span><span class="p">());</span>
    <span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>We moved all Codeception’s setUp and tearDown routine into parrent class and left you more clean <code class="language-plaintext highlighter-rouge">_before</code> and <code class="language-plaintext highlighter-rouge">_after</code> methods for your preperations.
They act just the same as <code class="language-plaintext highlighter-rouge">setUp</code> and <code class="language-plaintext highlighter-rouge">tearDown</code> for PHPUnit. So <code class="language-plaintext highlighter-rouge">_before</code> is executed before each test and <code class="language-plaintext highlighter-rouge">_after</code> after it.
Tests should look more clean now. If your tests already have setUp and tearDown methods nothing is changed for them.</p>

<h3 id="accessing-modules-in-unit-tests">Accessing Modules in Unit Tests</h3>

<p>Another nice feature for Symfony2 users and not only them. Form now on you can access a module from your unit test.
This is done to access public properties of your module. For example, here is how you can retrieve a <strong>Symfony Dependency Injection Container</strong>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">protected</span> <span class="k">function</span> <span class="n">_before</span><span class="p">()</span> 
<span class="p">{</span>
	<span class="cd">/**
	* @var $container Symfony\Component\DependencyInjection\Container
	*/</span>
	<span class="nv">$container</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'Symfony2'</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">container</span><span class="p">;</span>
	<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">em</span> <span class="o">=</span> <span class="nv">$container</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s1">'doctrine'</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Also we’d like to announce the upcoming modules for <strong>Yii</strong> and <strong>Laravel</strong> frameworks.</p>

<p>In the meantime we will release more complete guides on How to integrate framework to Codeception.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li>Composer build is finally is stable and doesn’t require <code class="language-plaintext highlighter-rouge">minimal-stability: dev</code>. Thanks to: <a href="https://github.com/jacobkiers">jacobkiers</a>.</li>
  <li>Adding support of <code class="language-plaintext highlighter-rouge">pecl_http</code> by <a href="https://github.com/phpcodemonkey">phpcodemonkey</a>.</li>
  <li>Methods of Guy received documentation and examples (phar bug).</li>
  <li><code class="language-plaintext highlighter-rouge">generate:cest</code> command requires a tested class name no more.</li>
  <li><a href="https://github.com/Codeception/Codeception/issues/117">PostgreSQL</a> driver improved .</li>
</ul>

<h3 id="update">Update</h3>

<p><a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>

<p>for composer version</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<p>or via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Codecepion 1.5.1</title>
      <link>https://codeception.com/01-16-2013/codeception-1-5-1.html</link>
      <pubDate>Wed, 16 Jan 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-16-2013/codeception-1-5-1</guid>
      <description><![CDATA[ <p>You know, it’s a common situation when just after the brand major release comes a small release with patches and bugfixes. Yeah, Codeception 1.5.1 has nothing to surprise you, still it’s reommended to upgrade if you are running the <a href="https://github.com/Codeception/Codeception/issues/107">phar vs composer issue</a>. 
As we discovered with the help of <a href="https://github.com/alexshelkov">alexshelkov</a>, that Codeception packaged phar was trying to load PHP libraries from a local composer installation. So if you was trying phar version in project that already use composer, you may have seen strange errors.</p>

<p>This bug was fixed and last version 1.5.1, ready for download.</p>

<p>A simple improvement was introduced by <a href="https://github.com/Dev-Man">DevMan</a>. It allows you to execute Codeception from any directory if you set a path to config file with a <code class="language-plaintext highlighter-rouge">-c</code> parameter.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar run <span class="nt">-c</span> /var/myproject/codeception.yml</code></pre></figure>

<p>And finally we are back green on Travis. We had some issues with Travis infrastructure (not the tests), but we managed to solve them. Did you know that it takes <strong>8 minutes</strong> to run all internal tests of Codeception? Yeah, we’ve got lots of tests )</p>

<p><a href="https://travis-ci.org/Codeception/Codeception"><img src="https://travis-ci.org/Codeception/Codeception.png?branch=master" alt="Build Status" /></a></p>

<h3 id="update">Update</h3>

<p>Please <a href="https://codeception.com/thanks.html">redownload</a> your <code class="language-plaintext highlighter-rouge">codeception.phar</code> for update:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">wget https://codeception.com/codecept.phar <span class="nt">-O</span> codecept.phar</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception released with CodeCoverage support</title>
      <link>https://codeception.com/01-08-2013/codeception-codecoverage.html</link>
      <pubDate>Tue, 08 Jan 2013 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-08-2013/codeception-codecoverage</guid>
      <description><![CDATA[ <p>We’d like to announce new Codeception 1.5 major release. This time our improvements are CodeCoverage and Remote CodeCoverage added. These features allows you to collect code coverage reports for all your tests: unit, functional, and acceptance and merge them together. So now you can review what parts of your applications are tested and which are not even for Selenium and PhpBrowser tests which are executed on a webserver.</p>

<p><a href="https://codeception.com/docs/11-CodeCoverage">Read more</a> in the new Guides chapter.</p>

<p>There is no magic in local codecoverage. <strong>XDebug</strong> and <strong>PHP_CodeCoverage</strong> libraries do their job. The tricky thing is remote codecoverage. We attach small script into application’s front controller. When a special header is sent this script starts to collect coverage information. And in the end of tests, this data is merged, serialized and sent back to Codeception. So you can test and collect coverage report even on staging servers in real environment.</p>

<p><img src="https://codeception.com/images/coverage.png" alt="code coverage" /></p>

<p>Thanks to <strong><a href="https://github.com/tiger-seo">tiger-seo</a></strong> for codecoverage feature. He did a great job developing a remote script <code class="language-plaintext highlighter-rouge">c3.php</code> which is a unique in it’s way.</p>

<p>But back to Codeception. As you may’ve noticed our website is updated too. Documentation was improved, search was added, and nice <a href="https://codeception.com/quickstart">Quickstart</a> page added too. So if you didn’t try Codeception yet, it’s very easy to start now. In only 6 steps.</p>

<h3 id="modules">Modules</h3>

<p>Two useful modules were introduced by <a href="https://github.com/judgedim">judgedim</a>. We have support of <a href="https://codeception.com/docs/modules/MongoDb">MongoDb</a> and <a href="https://codeception.com/docs/modules/Redis">Redis</a> now. They both can clean up your storages between tests and Mongo can perform checks in your collections. So If you are working with NoSQL databases, you should try them in your tests. If you use different NoSQL databases, please submit your patches, and they will be included in next release.</p>

<h3 id="ux-improvements">UX Improvements</h3>

<p>Now you can execute a test by providing relative path to test, like.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar tests/acceptance/SignInCept.php</code></pre></figure>

<p>This small tweak imprioves user experience for *nix users as they can use autocompletion when running a test.</p>

<p>Also you can run test from one specific directory, i.e. match a group of tests:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar tests/acceptance/admin</code></pre></figure>

<h3 id="bugfixes">Bugfixes</h3>

<p>Composer package is works again. It’s really hard to follow the stability in the world of constant changes, so we recommend use of <code class="language-plaintext highlighter-rouge">phar</code> for testing, just because it’s prepackaged and always runs as expected. But if you use Composer it’s easy to add Codeception to your vendors and receive all new updates with new release. Don’t forget to mark <code class="language-plaintext highlighter-rouge">@stable</code> Codeception version.</p>

<h3 id="install">Install</h3>

<p>As usual, Codeception 1.5.0 can be <a href="https://codeception.com/thanks.html">downloaded from site</a>,</p>

<p>installed via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<h3 id="thanks">Thanks</h3>

<p>As you may’ve noticed all that guys who took part in developing Codeception are now shown on every page of this site. Thn this way we say thank for all our contributors and all guys who support this project, for all companies that adopt Codeception in their workflow.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Stop Simulating BDD, Write Tests</title>
      <link>https://codeception.com/12-20-2012/not-bdd.html</link>
      <pubDate>Thu, 20 Dec 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/12-20-2012/not-bdd</guid>
      <description><![CDATA[ <p>I keep receiving one question. Well, actually two: <strong>“What makes <a href="https://codeception.com">Codeception</a> different comparing to <a href="https://behat.org">Behat</a>“</strong>. And the next one: <strong>“Why can’t I write Codeception tests in human language like Behat does”</strong>. I think the time has come to answer this questions.</p>

<p>As you know, the Behat project is not only a tool but a methodology. The Behavior Driven Development concept requires that the User Stories to be written, and then executed as a test. <strong>Behat is a right tool for teams who strictly follow the BDD</strong> methodology. But what if you don’t? For what in the world you need tests written in plain English?</p>

<p>If you write a story like this, using Behat and MinkContext for example,</p>

<figure class="highlight"><pre><code class="language-gherkin" data-lang="gherkin"><span class="nf">Given </span>I am on <span class="s">"/product/1"</span>
<span class="nf">When </span>I click <span class="s">"Purchase"</span>
<span class="nf">And </span>I fill in <span class="s">"name"</span> with <span class="s">"Michael"</span>
<span class="nf">And </span>I fill in <span class="s">"credit"</span> with <span class="s">"321123123"</span>
<span class="nf">And </span>I click <span class="s">"Order"</span>
<span class="nf">Then </span>I should see <span class="s">"The product was purchased!"</span></code></pre></figure>

<p>you actually write test, and not a story. Because the feature you describe won’t change If you rename field “credit” to “credit card”, but the test will fail. You may change the text <em>“The product was purchased”</em> to <em>“iPhone5 was purchased. Thank you!”</em> and that will make test fail too. So you will rewrite the user story every time you change every detail that may affect passing test. In this case the manager who wrote this spec will debug and update user story to make the test pass.</p>

<p>And so your manager becomes tester. His role is now not only to deliver specifications to team but also to make this specifications written as tests and make them pass.</p>

<p>But what If you want one additional step to the scenario?</p>

<figure class="highlight"><pre><code class="language-gherkin" data-lang="gherkin"><span class="nf">Given </span>I am <span class="s">"/product/1"</span>
<span class="nf">When </span>I click <span class="s">"Purchase"</span>
<span class="nf">Then </span>I should see <span class="s">"1 product"</span> in the bin</code></pre></figure>

<p>For this step <code class="language-plaintext highlighter-rouge">see "1 product" in the bin</code> you should write a custom step. If only your manager knew PHP for it! Ideally to become manager + tester + PHP guru. But no, manager needs to ask your developer to write the necessary step. Thus, already two people are writing the test. And one of them knows PHP. And when you will hire a QA will you require a knowledge of PHP? Well, yep. Thus because you don’t want to disturb your PHP devs and assign them additional tasks.</p>

<p>When your product growths your tests becomes more and more complex. And you need to keep them updated for each change. When you use the plain English text, you don’t have a control over tests.  When your form don’t have a label you need to write custom step instead of <code class="language-plaintext highlighter-rouge">I fill in</code>, because it’s actually wrong to use CSS or XPath selectors inside a Behat feature. It’s not plain English text anymore with CSS. You need PHP developers to create additional steps.</p>

<p>Why Codeception is better testing tool? Well, just because it is a testing tool at first. Spend a day, to teach your manager/tester/qa PHP DSL, install a Netbeans or PHPStorm (or any other IDE), and start writing tests. Even when tests looks similarly to Behat features they give more power and control over the process.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/product/1'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Purchase'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="s1">'Michael'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'credit'</span><span class="p">,</span> <span class="s1">'321123123'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Order'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'The product was purchased!'</span><span class="p">);</span></code></pre></figure>

<p>This test in the process of evolution can be transformed into something more complex. You can use CSS and XPath everywhere, so when you change the “Order” button with an image, you can use it’s CSS and quickly update a test to make it pass. Also, you can move repeatable elements into variables and classes and make a test that looks like this:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="nc">ProductPage</span><span class="o">::</span><span class="no">URL</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#purchase'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="nv">$user_name</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'credit'</span><span class="p">,</span> <span class="nv">$user_credit</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'img a#order'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="nc">ProductPage</span><span class="o">::</span><span class="nv">$successMessage</span><span class="p">);</span></code></pre></figure>

<p>Just the same scenario. Well it’s a bit harder to read, as we added CSS selectors, but as you see this test pretty much more flexible. It can be easily refactored and improved without writing any custom method to helper.</p>

<p><strong>Don’t fall into a marketing trap</strong>. You will find yourself writing tests two times: as a feature in plain English and in code with PHP.</p>

<p>It’s better to have one person who can take a full control over test automation then, delegate some tasks to developers, some tasks to managers. If you are developer and you work on your own project. Why PHP is not suitable for you? Why do you want to write code 2 times: once in feature with Gherkin and second time in Context. Is it KISS? Is it DRY? I don’t think so.</p>

<p>Will Codeception support plain text test scenarios? Really, I <a href="https://gist.github.com/3796226">thought on that</a>. But I don’t want to put the limits. Using plain text makes impossible to use variables, loops, grabbers, and thus use <a href="https://codeception.com/10-30-2012/pro-tips-1.html">PageObject pattern</a>. Which is very important for solid and concrete test automation platform.</p>

<p>Behat is great BDD tool and it’s author @everzet also states: <a href="https://twitter.com/everzet/status/169745591654555648">don’t use it for functional testing</a>.
Choose the right tool for job.</p>

<p><strong>Disclaimer</strong>: I’m not very good in theory, I’m very practical guy. I won’t refer you to any published books or methodologies. But If you want an authority… Well, <strong>David Heinemeier Hansson</strong> (the creator of Rails) wrote in <a href="https://37signals.com/svn/posts/3159-testing-like-the-tsa">his blog</a>: <em>1”Don’t use Cucumber unless you live in the magic kingdom of non-programmers-writing-tests”</em>. And Behat is Cucumber for PHP. DHH is known for his dislike to popular BDD tools like RSpec or Cucumber. But he is very pragmatic and very scrupulous in testing.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Protips 2 - Extending Modules</title>
      <link>https://codeception.com/11-13-2012/protips-extending.html</link>
      <pubDate>Tue, 13 Nov 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/11-13-2012/protips-extending</guid>
      <description><![CDATA[ <p>Today, we will continue covering advanced topics on Codeception. The main power of Codeception is it’s modules, there are already plenty of them, even though you might want to extend one of them. Let’s say you are using <strong>Symfony2</strong> and you want to add additional actions, you actually miss in current module, like dealing with FOSUserBundle: registering, authenticating, etc.
You can create a helper and connect with Symfony2 module, get access to dependency injection container and do anything you need there. Sometimes you might want to change the module initialization scripts. This happens if your application configured in a custom way and module doesn’t work properly because of it.</p>

<p>In both cases you might want to improve current Symfony2 (or any other module) implementation. That’s pretty easy, because we can use just the simple OOP inheritance. You can create your own module <code class="language-plaintext highlighter-rouge">Symfony2Helper</code> and inherit it from default Symfony2 module. This module will act as a regular Helper, and should be placed to <code class="language-plaintext highlighter-rouge">tests/_helpers</code> dir.</p>

<p>In the next example we will redefine initialization for working with Symfony2 applications located in <code class="language-plaintext highlighter-rouge">app/frontend</code> path with Kernel class located in <code class="language-plaintext highlighter-rouge">app</code>.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">Symfony2Helper</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Module\Symfony2</span>
<span class="p">{</span>
	<span class="c1">// overriding standard initialization</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">_initialize</span><span class="p">()</span> <span class="p">{</span>
    	<span class="c1">// bootstrap</span>
        <span class="k">require_once</span> <span class="nb">getcwd</span><span class="p">()</span><span class="mf">.</span><span class="s1">'app/frontend/bootstrap.php.cache'</span><span class="p">;</span>
        <span class="c1">// kernel class</span>
        <span class="k">require_once</span>  <span class="nb">getcwd</span><span class="p">()</span><span class="mf">.</span><span class="s1">'/FrontendKernel.php'</span><span class="p">;</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FrontendKernel</span><span class="p">(</span><span class="s1">'test'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">boot</span><span class="p">();</span>

        <span class="nv">$dispatcher</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">kernel</span><span class="o">-&gt;</span><span class="nf">getContainer</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">get</span><span class="p">(</span><span class="s1">'event_dispatcher'</span><span class="p">);</span>
        <span class="nv">$dispatcher</span><span class="o">-&gt;</span><span class="nf">addListener</span><span class="p">(</span><span class="s1">'kernel.exception'</span><span class="p">,</span> <span class="k">function</span> <span class="p">(</span><span class="nv">$event</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">throw</span> <span class="nv">$event</span><span class="o">-&gt;</span><span class="nf">getException</span><span class="p">();</span>
        <span class="p">});</span>
    <span class="p">}</span>	
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Please, refer to the <code class="language-plaintext highlighter-rouge">_initialize</code> <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Module/Symfony2.php#L37">method implementation</a> to understand the default behavior. To get the idea whether you need to inherit and redeclare methods of module, you need to review it’s code. If you see your requirements can’t be met by using config options, please override.</p>

<p>By using inheriteance you can redeclare all the methods or initialization hooks you don’t like. The API of parent module is pretty clean and even when you use the <code class="language-plaintext highlighter-rouge">phar</code> version of Codeception, you can read it’s code on GitHub. If you stuck because Codeception module works improperly, you are free to fix that.</p>

<p>And yep, if your improved module is worth sharing with community, submit a patch and it will be added to official distribution. After all, that’s how the Open Source works.</p>

<p>Thanks for reading. Use Codeception professionally.</p>
 ]]></description>
    </item>
    
    <item>
      <title>ProTips in Managing UI</title>
      <link>https://codeception.com/10-30-2012/pro-tips-1.html</link>
      <pubDate>Tue, 30 Oct 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-30-2012/pro-tips-1</guid>
      <description><![CDATA[ <p>Hi, we’ve decided to start a pro tips post series on Codeception. We hadn’t too much time recently, because of the work on our startup <a href="https://bugira.com">Bugira</a>, and the release of community-driven catalog oj Javascript libraries - <a href="https://jster.net">Jster</a>. You should definitely visit Jster (and add it to bookmarks), as it contains more then <strong>800 javascript libraries</strong> for any needs in frontend development. But finally, We can get back to Codeception and tell about it’s best usage practices.</p>

<h3 id="tip-1-variables-for-ui-elements">Tip 1: Variables for UI elements</h3>

<p>You can write pretty complex tests using Codeception. When you have lots of them you may find that changing page UI elements can lead to refactoring all the tests. If you plan to develop a solid automation platform for your web application, consider putting all UI elements into the variables. In this case you can modify your tests pretty easy. If you see like you are creating too much tests, you should think on reorganizing them in a way that can act stable despite of changes in project. It’s really hard, features, designs, can constantly change and affect tests. But it’s possible to keep your tests stable if you use variables instead of raw values in tests.</p>

<p>Let’s say we have an acceptance test <code class="language-plaintext highlighter-rouge">tests/acceptance/CreateTaskCept.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create todo task'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/tasks'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'New Task'</span><span class="p">,</span><span class="s1">'Update a blog'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Add'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Update a blog'</span><span class="p">,</span> <span class="s1">'#tasks'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>What if we change the name of buttons and the DOM position of the element where “Update a blog” text should appear?
Let’s move this elements to a <code class="language-plaintext highlighter-rouge">_bootstrap</code> file and push them into variables.</p>

<p>In <code class="language-plaintext highlighter-rouge">tests/acceptance/_bootstrap.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$task_add_button</span> <span class="o">=</span> <span class="s1">'Add'</span><span class="p">;</span>
<span class="nv">$task_new_field</span> <span class="o">=</span> <span class="s1">'New Task'</span><span class="p">;</span>
<span class="nv">$tasks_list</span> <span class="o">=</span> <span class="s1">'#tasks'</span><span class="p">;</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And in <code class="language-plaintext highlighter-rouge">tests/acceptance/CreateTaskCept.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create todo task'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/tasks'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nv">$task_fill_field</span><span class="p">,</span><span class="s1">'Update a blog'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nv">$task_add_button</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Update a blog'</span><span class="p">,</span> <span class="nv">$tasks_list</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you see replacing values with variables shouldn’t affect the test readability while you choose proper names for UI elements.
We can also recommend to store user names, passwords, etc in bootstrap too. It will be automatically included on each test run. Use it.</p>

<h3 id="tip-2-use-pageobject">Tip 2: Use PageObject</h3>

<p>The PageObject is a pattern very popular among QA automation professionals. PageObject allows us to organize variables from a previous tip in more structured way.
Instead of using raw variables we will group them into a class and use them in test and helpers. But classes and constants can’t be added to <code class="language-plaintext highlighter-rouge">_bootstrap</code>, because bootstrap will be loaded before each test, so it will trigger an error: <strong>“Fatal: Cannot redeclare class”</strong>. Let’s deal with that by creating a new PHP file for TodoTask page class:</p>

<p>In <code class="language-plaintext highlighter-rouge">tests/acceptance/_todoTaskPage.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">TodoTaskPage</span> <span class="p">{</span>
	<span class="k">const</span> <span class="no">URL</span> <span class="o">=</span> <span class="s1">'/tasks'</span><span class="p">;</span>

	<span class="k">static</span> <span class="nv">$add_button</span> <span class="o">=</span> <span class="s1">'Add'</span><span class="p">;</span>
	<span class="k">static</span> <span class="nv">$new_field</span> <span class="o">=</span> <span class="s1">'New Task'</span><span class="p">;</span>
	<span class="k">static</span> <span class="nv">$list</span> <span class="o">=</span> <span class="s1">'#tasks'</span><span class="p">;</span>	
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Let’s add it to <code class="language-plaintext highlighter-rouge">tests/acceptance/_bootstrap.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">require_once</span> <span class="s1">'_todoTaskPage.php'</span><span class="p">;</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In this case you won’t get lost in where which UI element is located. Because in PageObject pattern the UI element is bound to a page, which we defined by the URL property. And here is the updated test:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create todo task'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="nc">TodoTaskPage</span><span class="o">::</span><span class="no">URL</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nc">TodoTaskPage</span><span class="o">::</span><span class="nv">$new_field</span><span class="p">,</span><span class="s1">'Update a blog'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="nc">TodoTaskPage</span><span class="o">::</span><span class="nv">$add_button</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Update a blog'</span><span class="p">,</span> <span class="nc">TodoTaskPage</span><span class="o">::</span><span class="nv">$list</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>After this update we have all the UI elements for todo task page kept in one place. Using and IDE you can easily find the right element and insert it into any test of your suite. Despite the raw variables <strong>classes and constants are accessible in helpers and unit tests</strong>. Also you can improve the page object classes with PHP’s OOP power. If you are using PHP 5.4 you can include global UI elements (menus, breadcrumbs) with traits.</p>

<p>Lets create a trait for menu component in <code class="language-plaintext highlighter-rouge">tests/acceptance/_menu.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">trait</span> <span class="nc">GlobalMenu</span> <span class="p">{</span>
	<span class="k">public</span> <span class="k">static</span> <span class="nv">$global_menu</span> <span class="o">=</span> <span class="s2">"//div[@id=menu]"</span><span class="p">;</span>

	<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">menuItem</span><span class="p">(</span><span class="nv">$index</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="k">return</span> <span class="k">self</span><span class="o">::</span><span class="nv">$global_menu</span><span class="mf">.</span><span class="s1">'/ul/['</span><span class="mf">.</span><span class="nv">$index</span><span class="mf">.</span><span class="s1">']'</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>We add it to <code class="language-plaintext highlighter-rouge">tests/acceptance/_bootstrap.php</code>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">require_once</span> <span class="s1">'_menu.php'</span><span class="p">;</span>
<span class="k">require_once</span> <span class="s1">'_todoTaskPage.php'</span><span class="p">;</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And we are using it in previously declared TodoTaskPage:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">TodoTaskPage</span> <span class="p">{</span>

	<span class="kn">use</span> <span class="nc">GlobalMenu</span><span class="p">;</span>

	<span class="k">const</span> <span class="no">URL</span> <span class="o">=</span> <span class="s1">'/tasks'</span><span class="p">;</span>

	<span class="k">static</span> <span class="nv">$add_button</span> <span class="o">=</span> <span class="s1">'Add'</span><span class="p">;</span>
	<span class="k">static</span> <span class="nv">$new_field</span> <span class="o">=</span> <span class="s1">'New Task'</span><span class="p">;</span>
	<span class="k">static</span> <span class="nv">$list</span> <span class="o">=</span> <span class="s1">'#tasks'</span><span class="p">;</span>	
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And now we can use properties and methods of a trait included in class. Thus, TodoTaskPage, as any class that uses GlobalMenu trait can access a menu.
Let’s write a new test for checking that menu contains a button to create a task.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'check task creation link is in a menu'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="nc">TodoTaskPage</span><span class="o">::</span><span class="no">URL</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Create Task'</span><span class="p">,</span> <span class="nc">TodoTaskPage</span><span class="o">::</span><span class="nf">menuItem</span><span class="p">(</span><span class="mi">3</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>If you think on layout components as a traits and pages as classes, you can reorganize your UI elements in a very flexible way. Changes in markup or texts won’t affect a tests, as you can easily update all the tests that rely on that element. You can even teach your template developer to update the corresponding PageObject each time she changes template.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Codeception is simple, yet powerful tool for test automation. If you plan to use test automation for the enterprise level projects, it’s better to start with proper organization. As we think on architecture before writing the first line of code, we should think on scalable architecture of tests platform. Using PageObject and variables can dramatically improve the reusability (and keep KISS and DRY principles) of your tests.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Error Reporting and XmlRPC</title>
      <link>https://codeception.com/10-22-2012/xml-rpc-release.html</link>
      <pubDate>Mon, 22 Oct 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-22-2012/xml-rpc-release</guid>
      <description><![CDATA[ <p>It looks like a good time for the new release! Do you agree?</p>

<p>And yes, there are enough changes to announce Codeception 1.1.5. In this release we concentrated mostly on fixing bugs and improving error reporting.
But the most important change, that from now Codeception uses <strong>PHPUnit 3.7</strong>. This PHPUnit version doesn’t have that much BC breaks as previous one, so we hope you will not notice this change.</p>

<p>Some tasty features were added too. But let’s start with error reporting.</p>

<ul>
  <li>In stack trace PHP files of yours will be highlighted (if you use colors, of cource)</li>
  <li>No more <code class="language-plaintext highlighter-rouge">ERROR</code> with no descriptions, every error have stack trace and description</li>
  <li>Errors are displayed better, stack traces avaible only with <code class="language-plaintext highlighter-rouge">--debug</code> options</li>
</ul>

<h3 id="xml-rpc-module">XML-RPC Module</h3>
<p><strong><a href="https://github.com/tiger-seo">Tiger SEO</a></strong> added just another useful module for testing XML-RPC web services. 
It requires ‘php_xmlrpc’ extension and <code class="language-plaintext highlighter-rouge">PhpBrowser</code> module to run. With this module you can perform XMLRPC calls and check the responses.
You can review the code at <a href="https://github.com/Codeception/Codeception/blob/master/src/Codeception/Module/XMLRPC.php">GitHub</a> or <a href="https://codeception.com/docs/modules/XMLRPC">read the docs</a>.</p>

<h3 id="minor-features-and-bugfixes">Minor Features and Bugfixes</h3>

<ul>
  <li>Composer package fixed</li>
  <li><code class="language-plaintext highlighter-rouge">grabServiceFromContainer</code> method added to Symfony2 module</li>
  <li>REST <a href="https://github.com/Codeception/Codeception/pull/75">fixes</a> and <a href="https://github.com/Codeception/Codeception/pull/71">improvements</a> by <strong>tiger-seo</strong></li>
  <li>Fix for using <code class="language-plaintext highlighter-rouge">seeInDatabase</code> command with PostgreSQL</li>
  <li><code class="language-plaintext highlighter-rouge">build</code> command is not generating methods with the same names anymore</li>
  <li>no need to run <code class="language-plaintext highlighter-rouge">build</code> command just after <code class="language-plaintext highlighter-rouge">bootstrap</code></li>
</ul>

<h3 id="bc-breaks-to-aware-of">BC breaks to aware of</h3>

<p>There could be some BC breaks, you should know about.
Before 1.1.5 you could start writing tests without defining a page. Codeception opened the root url “/” by default. So all actions were performed on home page. But opening the page before each test is not the best idea, especially if we test REST/SOAP web service. We just spend time for useless action. So whenever you write acceptance test, please start it with <code class="language-plaintext highlighter-rouge">amOnPage</code> action. This change didn’t affect the functional tests (for now).</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span> 
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span> <span class="c1">// required!
</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Also, we did some changes for 2-steps tests loading, intrudoced in 1.1. At the first stage we read the test contents, in the next we execute it. From now on this stages are isolated, variables from preload will not pass to run. This will require loading of bootstrap file two times. Be prepared for that and optimize your bootstrap file.</p>

<p>As usual, Codeception 1.1.5 can be <a href="https://codeception.com/thanks.html">downloaded from site</a>,</p>

<p>installed via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>5 Reasons to Try Codeception</title>
      <link>https://codeception.com/10-03-2012/5-reasons.html</link>
      <pubDate>Wed, 03 Oct 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/10-03-2012/5-reasons</guid>
      <description><![CDATA[ <p>Codeception is PHP framework for testing web applications in BDD-style. It was started about a year ago, as a plugin for symfony1, to speed up and simplify functional testing inside the framework. But as time passed, Codeception evolved to standalone project, with support of various frameworks and engines. It’s built on top of  wonderful <strong>PHPUnit</strong>, but with aim for acceptance, and functional scenario driven tests. In this post we will remind why you may like Codeception and why we feel it’s awesome.</p>

<h2 id="1-php">1. PHP!</h2>

<p>Yes, the first reason is PHP. If you are PHP developer it’s natural you would like to write tests in PHP. Codeception provides you the best way to do so. 
Any IDE with code completion and syntax highlighting will help you write tests faster and without stupid syntax mistakes. Usage of PHP inside of tests unleashes the true power and control over the test flow. You can use your application classes or create testing helpers. Also you can get values (with grabbers) from results and use them in your tests. You just control everything. And yep, use everything you like from PHPUnit.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'launch missiles from my website'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/launch'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Launch Missiles!'</span><span class="p">)</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Missiles launched'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="2-simplicity">2. Simplicity</h2>

<p>You know, KISS is our first principle. Even Codeception requires basic knowledge of PHP it narrows testing to using PHP DSL where all actions are defined with user’s perspective. Just enter the <code class="language-plaintext highlighter-rouge">$I-&gt;</code> and select action from a list and put parameters. That’s how a test is written. Also add minimal configuration in YAML format, and installation by downloading a <strong>single phar archive</strong>. It’s really that simple.</p>

<p><img src="https://dl.dropbox.com/u/930833/codecept.png" alt="codecept" /></p>

<h2 id="3-multi-framework-and-multi-backend">3. Multi-Framework and Multi-Backend</h2>

<p>You decided to migrate your application from <strong>symfony1</strong> to <strong>Symfony2</strong>, from <strong>Kohana</strong> to <strong>Zend</strong>? You decided to test with <strong>Selenium</strong> inside a real browser? Your tests will run inside chosen the engine, no matters what happen. Codeception using one common syntax for all the backends. Frameworks support allows you to create more complex assertion and check the internals of your application, not only the visible part.</p>

<h2 id="4-complex-tests">4. Complex Tests</h2>

<p>Here comes a QA and says: I need <strong>XPath</strong>, I need complex selectors, I need to test UI elements strictly. No problems! You can use CSS selectors, XPath locators and even combine them with <code class="language-plaintext highlighter-rouge">Locator</code> class. You can also test your <strong>SOAP</strong> and <strong>REST</strong> webservices, pragmatical use XMLs (defined in jQuery-like style) and JSONs (as PHP arrays). Despite Codeception tend to be simple, it can be used by QAs creating solid tests automation platform.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'New User'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#user_1 .user_new'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'//*[@id = '</span><span class="n">user_1</span><span class="s1">']/descendant::a'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Title'</span><span class="p">,</span> <span class="nc">Locator</span><span class="o">::</span><span class="nf">combine</span><span class="p">(</span><span class="s1">'h1'</span><span class="p">,</span><span class="s1">'h2'</span><span class="p">,</span><span class="s1">'h3'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nc">Locator</span><span class="o">::</span><span class="nf">tabIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">,</span> <span class="nc">Locator</span><span class="o">::</span><span class="nf">href</span><span class="p">(</span><span class="s1">'/login.php'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h2 id="5-data">5. Data</h2>

<p>Tests isolation is a problem. Most of testing frameworks puts it’s solving to your shoulders. But Codeception tries to fetch your needs and provide Data cleanup from the box. With the <code class="language-plaintext highlighter-rouge">Db</code> module you can repopulate database (<strong>MySQL</strong>, <strong>PostgreSQL</strong>, …), after each run, use SQLite (for faster testing), or just run all tests inside transaction (in functional or unit testing). Also Codeception have modules for using and cleaning <strong>Memcache</strong> and <strong>AMQP</strong> storages.</p>

<h2 id="and-finally">And Finally!</h2>

<p>And just to mention, the results of tests are readable to non-technical guys. When you export result in HTML you will see the cool colored page with all passed steps described in pure English. Also test results are readable to robots: export result as XML and the CI-server (Jenkins, Bamboo) will use them.</p>

<p>If you are still deciding weather or not to test your application, start doing it now. And Codeception is the right tool for this.</p>
 ]]></description>
    </item>
    
    <item>
      <title>The Locator Class</title>
      <link>https://codeception.com/09-24-2012/locator.html</link>
      <pubDate>Mon, 24 Sep 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-24-2012/locator</guid>
      <description><![CDATA[ <p>In the latest Codeception 1.1.4 new <code class="language-plaintext highlighter-rouge">Locator</code> class was introduced. Basically it should simplify your life in writing complex XPath or CSS locators. Right now it has minimal, yet useful functionality.</p>

<h4 id="combine">Combine</h4>

<p>Locator can combine two locators using <code class="language-plaintext highlighter-rouge">OR</code> operand:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Util\Locator</span><span class="p">;</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Title'</span><span class="p">,</span> <span class="nc">Locator</span><span class="o">::</span><span class="nf">combine</span><span class="p">(</span><span class="s1">'h1'</span><span class="p">,</span><span class="s1">'h2'</span><span class="p">,</span><span class="s1">'h3'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This will search for <code class="language-plaintext highlighter-rouge">Title</code> text in either <code class="language-plaintext highlighter-rouge">h1</code>, <code class="language-plaintext highlighter-rouge">h2</code>, or <code class="language-plaintext highlighter-rouge">h3</code> tag. You can also combine CSS selector with XPath locator:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Util\Locator</span><span class="p">;</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nc">Locator</span><span class="o">::</span><span class="nf">combine</span><span class="p">(</span><span class="s1">'form input[type=text]'</span><span class="p">,</span><span class="s1">'//form/textarea[2]'</span><span class="p">),</span> <span class="s1">'qwerty'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As a result the Locator will produce a mixed XPath value that will be used in fillField action.</p>

<h4 id="tabindex">tabIndex</h4>

<p>Do you often use the <code class="language-plaintext highlighter-rouge">TAB</code> key to navigate through the web page? How do your site respond to this navigation? 
You could try to match elements by their tab position using <code class="language-plaintext highlighter-rouge">tabIndex</code> method of <code class="language-plaintext highlighter-rouge">Locator</code> class.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Util\Locator</span><span class="p">;</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nc">Locator</span><span class="o">::</span><span class="nf">tabIndex</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="nc">Locator</span><span class="o">::</span><span class="nf">tabIndex</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="p">,</span> <span class="s1">'qwerty'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<h4 id="href">href</h4>

<p>Does the page contain link wo specified URL? Check that easily with <code class="language-plaintext highlighter-rouge">href</code> method of <code class="language-plaintext highlighter-rouge">Locator</code> class.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Util\Locator</span><span class="p">;</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Log In'</span><span class="p">,</span> <span class="nc">Locator</span><span class="o">::</span><span class="nf">href</span><span class="p">(</span><span class="s1">'/login.php'</span><span class="p">));</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And that’s all folks for today. We are sure the locator class will evolve to simplify writing complex locators. If you have ideas what methods should be added, post them here. Or, which is better, patch this class and send Pull Request to Github.</p>
 ]]></description>
    </item>
    
    <item>
      <title>YetAnotherRelease.</title>
      <link>https://codeception.com/09-14-2012/yet-another-release.html</link>
      <pubDate>Fri, 14 Sep 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/09-14-2012/yet-another-release</guid>
      <description><![CDATA[ <p>Codeception 1.1.3 and then 1.1.4 was released during last month. In this post I will summarize the changes happened in this minor updates. The 1.1.3 version fixed one bug pointed by <strong>Nastya Ahramenko</strong>. Yep, only one bug. But it was pretty cool for me to mention it and make a release for it.</p>

<p>Nastya wrote:</p>

<p>If the web-page contains two similar links, then the second link is not opened.
For example:</p>

<ol>
  <li>Page contains two links: “Test Link” is first link, “Test” is second link</li>
  <li>Create test with the following steps</li>
</ol>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Test Link'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Test'</span><span class="p">);</span></code></pre></figure>

<p>Both steps open the first link.</p>

<p>Actually we can discuss if it’s a bug or a feature. But, it’s more bug then a feature. This occur due to XPath locators in <em>Mink</em> and <em>BrowserKit</em> libraries. Codeception is a wrapper for Mink and BrowserKit, so there is no reason why it can’t be done right. So, Codeception is solving this bug by seraching the strictly matched object at first, and then is trying to find it by more complex XPath locator. I.e., at first it will try to locate <code class="language-plaintext highlighter-rouge">&lt;a href="#"&gt;Test&lt;/a&gt;</code> and if it’s not found will match the <code class="language-plaintext highlighter-rouge">&lt;a href="#"&gt;Test Link&lt;/a&gt;</code>.</p>

<p>That’s all about 1.1.3</p>

<h3 id="and-now-what-about-114">And now what about 1.1.4?</h3>

<p>There are pretty much fixes from other contributors. Thanks for anyone sending me pull requests and patches. Here are the changes done by this awesome guys!</p>

<ul>
  <li><a href="https://github.com/Codeception/Codeception/pull/69">ZombieJS fix</a> for newer Mink version compatibility by <strong>synchrone</strong>.</li>
  <li><a href="https://github.com/Codeception/Codeception/pull/66">Codeception\Module\Unit.seeExceptionThrown doesn’t fail</a> when no exception is thrown by <strong>lostintime</strong>.</li>
  <li><a href="https://github.com/Codeception/Codeception/pull/61">Symfony2.1 compatibility fix and reinvention of package building</a> by <strong>ZloeSabo</strong>.</li>
  <li>Various autoload fixes by <strong>flaviozantut</strong> and <strong>lostintime</strong>.</li>
  <li><a href="https://github.com/Codeception/Codeception/issues/59">No setProperty method in CodeGuy</a> by <strong>ZloeSabo</strong>.</li>
  <li>Also, useful XPath matching methods added to SOAP</li>
  <li>Memcache module supports now either <em>Memcache</em> or <em>Memcached</em> lib.</li>
</ul>

<h3 id="selenium2-module-improvements">Selenium2 module improvements</h3>

<ul>
  <li>Dealing with <a href="https://github.com/Codeception/Codeception/pull/60">confirm and alert popups</a> by <strong>f0rm4t</strong>.</li>
  <li><a href="https://github.com/Codeception/Codeception/pull/64">Methods SwitchToWindow and SwitchToIFrame added to Selenium2 module</a> by <strong>f0rm4t</strong>.</li>
</ul>

<h2 id="define-actions-beforehand">Define Actions Beforehand</h2>

<p>From now on it’s much easier to define actions in helpers. You can write a method that is not defined yet, and then run new <code class="language-plaintext highlighter-rouge">analyze</code> command to append new commands to helper classes. It’s quite useful when tester writes a test and needs some new actions to define. When you run</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php codecept.phar analyze suitename<span class="sb">`</span></code></pre></figure>

<p>you will be notified on all methods which do not exist in modules, and you will be asked to create them in helpers. Just try!</p>

<h2 id="new-locator-class">New Locator class</h2>

<p>XPath locators are very powerful but are pretty hard to write and maintain. We decided to provide some useful functions to help writing locators better. Try new <code class="language-plaintext highlighter-rouge">Codeception\Util\Locator</code> for that. It will be described in next blogpost. Stay in touch.</p>

<p>As usual, Codeception 1.1.4 can be <a href="https://codeception.com/thanks.html">downloaded from site</a>,</p>

<p>installed via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception with AMQP and Memcached</title>
      <link>https://codeception.com/08-28-2012/codeception-memcached-amqp.html</link>
      <pubDate>Tue, 28 Aug 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-28-2012/codeception-memcached-amqp</guid>
      <description><![CDATA[ <p>Good news, everyone! Codeception 1.1.2 released. And it’s hard to list everything that were improved and fixed, but i will try.
With the help of our active contributor <strong><a href="https://github.com/tiger-seo">tiger.seo</a></strong> Codeception got an <a href="https://codeception.com/docs/modules/AMQP">AMQP</a> module wich allows to manipulate queue engines, like <strong>RabbitMQ</strong>. You can use this module if you need to clear queues between tests. Also, new <a href="https://codeception.com/docs/modules/Memcache">Memcache</a> module was introduced. You can perform simple checks and use data from your Memcache storage in tests. Guys, it’s very simple to contribute to Codeception. All new modules are welcome, they can grow from your local helpers and become part of this library. Just fork Codeception, add a module and send me a pull request!</p>

<h3 id="ux-improvements">UX Improvements</h3>

<p>You should regenerate your guy-classes after this update with the <code class="language-plaintext highlighter-rouge">build</code> command. Rebuilt Guy-classes will contain full documentation for each method and link to the source code of underlying method. Also, with the help of <em>tiger.seo</em> Codeception got better <strong>PHPStorm</strong> integration. Codeception when run in PHPStorm console outputs stack traces that is recognized by PHPStorm. So you can click on any file name and move to it in IDE.</p>

<h3 id="save-scenarios-as-html">Save Scenarios as HTML</h3>

<p>You know that there is <code class="language-plaintext highlighter-rouge">--html</code> option which saves results of running tests in HTML. But now you can save the test scenarios in HTML without running them. That’s quite useful if you want to save test scenarios into your company’s wiki. The HTML format can inserted into Confluence, for example. And now testers, managers, and developers will have the test scenarios up to date. Yep, thanks again to <em>tiger.seo</em>.</p>

<h2 id="pear-updates">PEAR Updates</h2>

<p>PEAR package was completely redesigned. Codeception is not using PEAR as a dependency manager anymore, Composer is ok. But PEAR is quite useful if you want a system-wide install, and simple call to Codeception with <code class="language-plaintext highlighter-rouge">codecept</code> command. PEAR package now contains all dependent modules and doesn’t require PHPUnit or Mink installed anymore. That will prevent possible conflicts and reduce level of PEAR-related wtfs.</p>

<h2 id="bugs-fixed">Bugs Fixed</h2>

<ul>
  <li>comments is shown again in console and in html output.</li>
  <li>bug with exception in <a href="https://github.com/Codeception/Codeception/issues/48">printFail</a> method.</li>
  <li><a href="https://github.com/Codeception/Codeception/pull/45">js files</a> were not added to phar archive. Thanks to <a href="https://github.com/f0rm4t">f0rm4t</a>.</li>
  <li><a href="https://github.com/Codeception/Codeception/pull/46">fix tests</a> filename to be presented with relative path. By tiger.seo.</li>
  <li>unable to send more than 1 parameters using <a href="https://github.com/Codeception/Codeception/pull/54">SOAP.sendSoapRequest</a> by <a href="https://github.com/lostintime">lostintime</a></li>
  <li><a href="https://github.com/Codeception/Codeception/pull/43">DB module is not cleaned</a> after the last test. By tiger.seo.</li>
</ul>

<p>Codeception 1.1.2 can be <a href="https://codeception.com/thanks.html">downloaded from site</a>,</p>

<p>via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Major Codeception Update</title>
      <link>https://codeception.com/08-07-2012/major-codeception-update.html</link>
      <pubDate>Tue, 07 Aug 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/08-07-2012/major-codeception-update</guid>
      <description><![CDATA[ <p>Hi, last week Codeception got it’s first major update. Welcome the <strong>Codeception 1.1</strong>. Many core classes were refactored to solve the common issues and reduce the level of dark magic inside. Only white magic left. And that’s really cool ‘cause you don’t need to study to source code to implement your custom hooks now. Codeception is rapidly evolving to be the professional testing tool, ready to use by testers and developers through out the PHP world.</p>

<h2 id="test-execution-remastered">Test Execution Remastered</h2>

<p>Did you ever were wondered why you can’t receive values in test and pass it to next steps? To do something like this:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$user_name</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabTextFrom</span><span class="p">(</span><span class="s1">'#user_name'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'username'</span><span class="p">,</span> <span class="nv">$user_name</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Actually, there is no any good reason for not doing so. The only reason was - the code was not designed to execute test file in runtime. The steps were recorded, analyzed, and only then they were executed, without touching the test file again. That is the source of dark magic that was removed in Codeception 1.1. This magic was awful because you didn’t control the test execution. So, usage of custom PHP code in test was leading to unpredictable results. Even simple tasks was encouraged to be done in helpers, not in test code itself, to be run properly.</p>

<p>So what changed in Codeception 1.1? There is no magic in test execution, test file is required and executed, that’s all. Still the analyzes step is not skipped, so test is run two times: first to record scenario, validate and analyze all steps, second to execute them. With that simple idea you can use ANY php code in your tests if only you define the stage when it should be executed. The additional bootstrap files should be loaded one time before the analyses:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">preload</span><span class="p">())</span> <span class="p">{</span>
	<span class="k">require</span> <span class="s1">'_user_fixtures.php'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">loginAs</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="c1">// ...
</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>And when you need something to be executed in runtime, like cleaning the fixture data, please use the following:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// ..
</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">loginAs</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello, '</span><span class="mf">.</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$scenario</span><span class="o">-&gt;</span><span class="nf">running</span><span class="p">())</span> <span class="p">{</span>
	<span class="nv">$user</span><span class="o">-&gt;</span><span class="nb">delete</span><span class="p">();</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>In this example user is removed in the very end of scenario. <code class="language-plaintext highlighter-rouge">$scenario-&gt;running</code> method allows you to execute any code in the runtime. 
But please, always specify the stage when the custom code should be executed, or it will be executed 2 times.</p>

<p>In Codeception 1.0.x the <code class="language-plaintext highlighter-rouge">build</code> command was optional, when updating configuration. But now <strong>it’s required to run every time</strong> the modules are added or removed in suite config file. That’s the only new issue, but Guy-classes look much better now.</p>

<h2 id="grabbers">Grabbers</h2>

<p>As the result of changed described above, you can finally return values to scenario and use them in next steps. The new grabbers commands were introduced:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$text</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabTextFrom</span><span class="p">(</span><span class="nv">$element</span><span class="p">);</span>
<span class="nv">$value</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabValueFrom</span><span class="p">(</span><span class="nv">$form_field</span><span class="p">);</span>
<span class="nv">$attr</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabAttributeFrom</span><span class="p">(</span><span class="nv">$element</span><span class="p">,</span> <span class="s1">'attribute'</span><span class="p">);</span>

<span class="nv">$name</span> <span class="o">=</span> <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">grabFromDatabase</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="s1">'name'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'id'</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">));</span>
<span class="c1">// ....
</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>You can write your own grabbers. Just return values from your helper methods and you can use them in test.
Please review the modules to see new commands there!</p>

<h2 id="xpath-introduction">XPath Introduction</h2>

<p>Codeception is a tool for testing, and many testers like specifying locators by XPath. CSS selectors have their limitations, so why not to use XPath in tests too?
Sure, why not! You can freely use XPath selectors in your tests from now. But no new methods added for this! Really. The old methods were updated to support CSS and XPath as well. So whenever you need to pass a selector you can either pass CSS or XPath and Codeception is smart enough to guess what did you pass and how to use it.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'New User'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'#user_1 .user_new'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s2">"descendant::*[@id = 'user_1']/descendant::a"</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>All the methods where CSS was used were updated to support XPath. Try it!</p>

<h2 id="unit-tests">Unit Tests</h2>

<p>There was no common idea how to deal with unit tests in Codeception. As you know, Codeception can run standard PHPUnit tests as well as the hybrid scenario-driven unit tests. Scenario driven tests for many cases looked to complex to use. But they allowed to use Codeception modules in them. Why not to provide standard PHPUnit tests to use Codeception features? For Codeception 1.1 the <a href="https://codeception.com/docs/06-UnitTests-TEST">new chapter of Guides</a> describing unit tests is written. In brief: you can use the <code class="language-plaintext highlighter-rouge">CodeGuy</code> class inside your tests! Include any modules and use it as you need it. Use them to perform database cleanups, use them to check values in database, use them to work with file system. They are just wonderful helpers in your work.</p>

<p>And yep, new unit tests can be generated by command: <code class="language-plaintext highlighter-rouge">generate:test</code>.</p>

<h2 id="bugfixes-and-minor-changes">Bugfixes and Minor changes</h2>

<ul>
  <li>nested array logging was done by <a href="https://github.com/tiger-seo">tiger-seo</a></li>
  <li>ability to specify different configs for test execution, also done by (<a href="https://github.com/tiger-seo">tiger-seo</a>)</li>
  <li>ZF1 module fixes by <a href="https://github.com/insside">insside</a></li>
</ul>

<h2 id="upgrade-notes">Upgrade notes.</h2>

<ul>
  <li>right after updating Codeception please run the <code class="language-plaintext highlighter-rouge">build</code> command.</li>
  <li>remove all chained method executions in your tests. The $I object can return values, not self.</li>
</ul>

<p>Codeception 1.1 can be <a href="https://codeception.com/thanks.html">downloaded from site</a>,</p>

<p>via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

<p>P.S. Documentation was updated for 1.1 version.</p>
 ]]></description>
    </item>
    
    <item>
      <title>1.0.14 - Custom Assertions In Helpers</title>
      <link>https://codeception.com/07-12-2012/assertions-in-helpers.html</link>
      <pubDate>Thu, 12 Jul 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/07-12-2012/assertions-in-helpers</guid>
      <description><![CDATA[ <p>Hi, that’s been a while from the last release. But still Codeception is evolving. And today’s release notes I’m going to start with some thoughts on Codeception installation strategy.</p>

<p>For a long time a PEAR was the primary method for install. It had some issues and develoeprs got stuck with it. Nowdays alternative is a [Composer[(https://packagist.org)] which Codeception uses too. But nevertheless we consider it a bit complex too. Codeception is tool where everything is kept simple. We are trying to make it work even for junior developers and testers. So our primary goal is to provide a standalone version ‘codecept.phar’ which was introduced recently. In future version we will try to make it autoupdate itself (as Composer does).</p>

<p>It’s really cool cause it simplifies integration with CI systems and has less requirements to your PHP environment. Right now Codeception phar archive includes Symfony Components, Mink, PHPUnit in one file. So if you ever wanted to run PHPUnit tests without PEAR, the Codeception can be used that way too.</p>

<p>The major feature is related to current installation strategy. We finally added custom assertions to modules and user helper classes. Before that you should have used PHPUnit’s static methods for assertions. But now you can just write <code class="language-plaintext highlighter-rouge">this-&gt;assertXXX</code> in a helper class.</p>

<p>In next example we connect PhpBrowser module to helper and use assertion to check a menu exists for current user.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">WebHelper</span> <span class="k">extends</span> <span class="err">\</span><span class="nc">Codeception\Module</span> <span class="p">{</span>

	<span class="k">function</span> <span class="n">seeEditingToolsMenu</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="nv">$content</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">getModule</span><span class="p">(</span><span class="s1">'PhpBrowser'</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">session</span><span class="o">-&gt;</span><span class="nf">getPage</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">getContent</span><span class="p">();</span>
		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertContains</span><span class="p">(</span><span class="s1">'&lt;a id="menu" href="#"&gt;Edit Post&lt;/a&gt;'</span><span class="p">,</span><span class="nv">$content</span><span class="p">);</span>
	<span class="p">}</span>

<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The <a href="https://codeception.com/docs/03-Modules#helpers">Helpers</a> section in Guides was totally rewritten to represent this change and provide more examples.</p>

<p>In this release a new module <a href="https://codeception.com/docs/modules/WebDebug">WebDebug</a> was intorduced. It provides means to make screenshots with a single command. In case a screenshot can’t be saved, it tries at least save the HTML response to file. After the test you can review all saved files to see what actually happened during test.</p>

<p>Thanks to Andrey Popov for contributions.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">click</code> method for frameworks now accepts CSS selectors.</li>
</ul>

<p>This is Codeception 1.0.14. Download <a href="https://codeception.com/thanks.html">new version</a> to run tests or update</p>

<p>via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Test WebServices With Codeception</title>
      <link>https://codeception.com/06-19-2012/testing-webservices.html</link>
      <pubDate>Tue, 19 Jun 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/06-19-2012/testing-webservices</guid>
      <description><![CDATA[ <p>Codeception testing framework got significant improvements during last week. The first and the major one is that you don’t even need PEAR and Composer to execute tests. Only one file <code class="language-plaintext highlighter-rouge">codecept.phar</code> required. This might save your time and mind of your testers.</p>

<p>So Installation is much simplier now:</p>

<ol>
  <li>
    <p><a href="https://codeception.com/thanks.html">Download</a> archive.</p>
  </li>
  <li>
    <p>Execute it with PHP <code class="language-plaintext highlighter-rouge">php codecept.phar</code></p>
  </li>
</ol>

<p>Now you can start generating a test suite with  <code class="language-plaintext highlighter-rouge">php codecept.phar bootstrap</code> or execute existing tests with <code class="language-plaintext highlighter-rouge">php codecept.phar run</code>.</p>

<p><a href="https://codeception.com/doc">Documentation</a> section was created. New section Reference was added. There you can review Codeception commands and configuration values.</p>

<p>But the most cool stuff is new module for <em>testing web services</em>!</p>

<p>Modules for <a href="https://codeception.com/docs/modules/SOAP">SOAP</a> and <a href="https://codeception.com/docs/modules/REST">REST</a> were added recently. You know it’s always hard to test the API manually. So why not to automate it?</p>

<p>This API modules keeps simple manner in describing tests. Take a look at sample REST test.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ApiGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create a new user by API'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amHttpAuthenticated</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">,</span><span class="s1">'123456'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveHttpHeader</span><span class="p">(</span><span class="s1">'Content-Type'</span><span class="p">,</span><span class="s1">'application/x-www-form-urlencoded'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendPOST</span><span class="p">(</span><span class="s1">'/users'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span> <span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseCodeIs</span><span class="p">(</span><span class="mi">200</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseIsJson</span><span class="p">();</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeResponseContainsJson</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'result'</span> <span class="o">=&gt;</span> <span class="s1">'ok'</span><span class="p">));</span></code></pre></figure>

<p>And here goes a sample SOAP test:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="err">\</span><span class="nc">Codeception\Utils\Soap</span><span class="p">;</span>

<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ApiGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create a new user thorough API'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveSoapHeader</span><span class="p">(</span><span class="s1">'Auth'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'token'</span> <span class="o">=&gt;</span> <span class="s1">'123123'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">sendSoapRequest</span><span class="p">(</span><span class="s1">'CreateUser'</span><span class="p">,</span> <span class="nc">Soap</span><span class="o">::</span><span class="nf">request</span><span class="p">()</span>
	<span class="o">-&gt;</span><span class="nc">User</span>
		<span class="o">-&gt;</span><span class="nc">Name</span><span class="o">-&gt;</span><span class="nf">val</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">)</span><span class="o">-&gt;</span><span class="k">parent</span><span class="p">()</span>
		<span class="o">-&gt;</span><span class="nc">Email</span><span class="o">-&gt;</span><span class="nf">val</span><span class="p">(</span><span class="s1">'davert@codeception.com'</span><span class="p">);</span>
<span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeSoapResponseIncludes</span><span class="p">(</span><span class="nc">Soap</span><span class="o">::</span><span class="nf">response</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">result</span><span class="o">-&gt;</span><span class="nf">val</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span></code></pre></figure>

<p>Ok, the one thing you may have noticed. We are working with JSON in first case and XML in second. But there is no JSON or XML in code! Well, we could have used it, but we didn’t. Just because we can use PHP to set data in this formats. Json is built from PHP arrays and for XML is used jQuery-like styled <a href="https://codeception.com/docs/reference/xmlbuilder">XMLBuilder</a> class. But you could possibly add a raw json or XMl into your tests. No problems with that!</p>

<p>Modules themselves are already documented and tested. Soon a complete guide on WebService API testing will be added.</p>

<p>The other thing worth to mention is new <em>finalizers</em> in test scenarios. If you need to execute code after test is finished and you don’t want to put it in helper use the <code class="language-plaintext highlighter-rouge">$scenario-&gt;finilize</code> method. See it’s usage example in new <a href="https://codeception.com/docs/08-Data#manual-cleanup">Manual Cleanup</a> section of Guides.</p>

<p>This is Codeception 1.0.11. Download <a href="https://codeception.com/thanks.html">new version</a> to run tests or update</p>

<p>via PEAR</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>New Codeception. Zombies and More.</title>
      <link>https://codeception.com/05-29-2012/zombies-and-more.html</link>
      <pubDate>Tue, 29 May 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-29-2012/zombies-and-more</guid>
      <description><![CDATA[ <p>This evening I released Codeception 1.0.9. The most important thing you may notice is documentation. It’s just better. It was improved by <a href="https://github.com/jonphipps">Jon Phipps</a>. Better phrasing goes to better understanding, right? But let’s move on to see the actual new features.</p>

<h3 id="zombies-are-coming">Zombies are coming!</h3>

<p>Two new modules were intoduced by Alexander Bogdanov @synchrone. It’s new <a href="https://codeception.com/docs/modules/Selenium2">Selenium2</a> module and <a href="https://codeception.com/docs/modules/ZombieJS">ZombieJS</a>.</p>

<p>Ok, you may know about Selenium. But what is the purpose of Zombie?</p>

<p>Tools like <strong>ZombieJS</strong>, (PhantomJS, and more) are built in order to run tests without a browser. And so they are called headless. They don’t require a browser window to start, they don’t show any interactions on screen.</p>

<p>Why do we need browser for testing web applications? Only browser-based javascript engines can run all the client side code. ZombieJS is one of them, taken from browser and produced as a standalone tool. It’s built with Node.js and requires Node.js, NPM, a C++ compiler and Python to install. Check out it’s <a href="https://zombie.js.org/">official site</a> for more information.</p>

<p>Thanks to <a href="https://mink.behat.org">Mink</a> from now on you can write ZombieJS tests inside Codeception just like tests for other cases.</p>

<h3 id="dont-run-too-fast">Don’t run too fast!</h3>

<p>Selenium and Selenium2 modules was updated with the new <code class="language-plaintext highlighter-rouge">delay</code> option. If Selenium performs actions faster the user, and javascript just can’t catch it it, you can slow down the execution by setting the <code class="language-plaintext highlighter-rouge">delay</code> param. It’s set in milliseconds and will perform pauses after each step in scenarios.</p>

<h3 id="composer-tricks">Composer Tricks</h3>

<p>Seems like the PHP WebScrapper <a href="https://github.com/fabpot/Goutte">Goutte</a> (which is used by PHPBroser module) has a new backend now. It has moved from Zend Framework 2 libraries to new lightweight HTTP client <a href="https://guzzlephp.org/">Guzzle</a>. So, no more Zend dependencies and long stack trackes. This change doesn’t affect PEAR users, cause this change arrive in PEAR packages yet.</p>

<p>Thanks again to all contributors and reporters.</p>

<p>Please update Codeception version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or via Composer</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>php composer.phar update</code></pre></figure>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.8 Released.</title>
      <link>https://codeception.com/05-08-2012/composer-release.html</link>
      <pubDate>Tue, 08 May 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/05-08-2012/composer-release</guid>
      <description><![CDATA[ <p>From this release you can install Codeception via <a href="https://getcomposer.org/">Composer</a>. If you have fucked up with PEAR it’s a good idea to try out brand new Composer.
It allows you to install Codeception with all it’s dependencies, even PHPUnit, without any usage of PEAR.</p>

<p>If you already use Composer add this lines int your composer.json to and update packages.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">    <span class="s2">"require"</span>: <span class="o">{</span>
        <span class="s2">"Codeception/Codeception"</span>: <span class="s2">"*"</span>
    <span class="o">}</span>,
    <span class="s2">"repositories"</span>: <span class="o">{</span>
        <span class="s2">"behat/mink-deps"</span>: <span class="o">{</span>
            <span class="s2">"type"</span>: <span class="s2">"composer"</span>,
            <span class="s2">"url"</span>:  <span class="s2">"behat.org"</span>
        <span class="o">}</span>
    <span class="o">}</span></code></pre></figure>

<p>From now on you can run Codeception with</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">php vendor/bin/codecept</code></pre></figure>

<p>If you are new to composer but you are troubled with PEAR, the <a href="https://codeception.com/install">installation guide</a> is updated for you.</p>

<p>Except this significant (but simple change) this release is all about bugfixing.</p>

<p>With the help of GitHub users <a href="https://github.com/ilex">ilex</a> and <a href="https://github.com/nike-17">nike-17</a> Kohana module was improved. 
Do you want to have a module for other frameworks? Maybe Yii, Fuel, CodeIgniter or Zend Framework 2? It’s really simple. You just need to write a proper <em>connector</em> and you can go with performing functional tests inside your application. Check the [Functional Testing]https://codeception.com/docs/05-FunctionalTests) section of documentation.</p>

<p>And some good news about documentation! <a href="https://github.com/jonphipps">Jon Phipps</a> has done a great job on editing the docs. Soon it will be published here. I know my English is not perfect. So I really appreciate any help in editing and reviewing documentation or blog posts.</p>

<p>Thanks to <a href="https://github.com/delmot">Sergii Grebeniuk</a> for a small patch on autoloading.</p>

<p>There was not too much unique features in this release. Maybe you have some ideas on what should be improved?</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.7 Released.</title>
      <link>https://codeception.com/04-05-2012/minor-release.html</link>
      <pubDate>Thu, 05 Apr 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/04-05-2012/minor-release</guid>
      <description><![CDATA[ <p>That was quite a long time after last version was released. This time we decided to skip version 1.0.6, just because 1.0.7 looks prettier.</p>

<p>With this release Codeception can be used in CI systems like <a href="https://www.jenkins.io/">Jenkins</a>. It’s very easy: you  just append ‘–xml’ option for running test and receive xml report in JUnit format stored in ‘tests/_log’ directory. Other popular formats like Json and TAP were added too. Here is a sample report.xml generated by Codeception test suite:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="nt">&lt;testsuites&gt;</span>
  <span class="nt">&lt;testsuite</span> <span class="na">name=</span><span class="s">"acceptance"</span> <span class="na">tests=</span><span class="s">"9"</span> <span class="na">assertions=</span><span class="s">"29"</span> <span class="na">failures=</span><span class="s">"0"</span> <span class="na">errors=</span><span class="s">"0"</span> <span class="na">time=</span><span class="s">"41.532108"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\BuildCept.php"</span> <span class="na">name=</span><span class="s">"test build command (Cli\BuildCept.php)"</span> <span class="na">assertions=</span><span class="s">"5"</span> <span class="na">time=</span><span class="s">"4.016982"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\GenerateCeptCept.php"</span> <span class="na">name=</span><span class="s">"generate sample cept (Cli\GenerateCeptCept.php)"</span> <span class="na">assertions=</span><span class="s">"5"</span> <span class="na">time=</span><span class="s">"15.401255"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\GenerateCestCept.php"</span> <span class="na">name=</span><span class="s">"generate sample cest (Cli\GenerateCestCept.php)"</span> <span class="na">assertions=</span><span class="s">"3"</span> <span class="na">time=</span><span class="s">"3.742880"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\GenerateScenariosCept.php"</span> <span class="na">name=</span><span class="s">"generate scenarios (Cli\GenerateScenariosCept.php)"</span> <span class="na">assertions=</span><span class="s">"3"</span> <span class="na">time=</span><span class="s">"3.668740"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\GenerateSuiteCept.php"</span> <span class="na">name=</span><span class="s">"generate sample suite (Cli\GenerateSuiteCept.php)"</span> <span class="na">assertions=</span><span class="s">"4"</span> <span class="na">time=</span><span class="s">"4.706381"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\RunWithHtmlCept.php"</span> <span class="na">name=</span><span class="s">"check xml reports (Cli\RunWithHtmlCept.php)"</span> <span class="na">assertions=</span><span class="s">"1"</span> <span class="na">time=</span><span class="s">"2.428402"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\RunWithJsonCept.php"</span> <span class="na">name=</span><span class="s">"check json reports (Cli\RunWithJsonCept.php)"</span> <span class="na">assertions=</span><span class="s">"2"</span> <span class="na">time=</span><span class="s">"2.692029"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\RunWithTapCept.php"</span> <span class="na">name=</span><span class="s">"check tap reports (Cli\RunWithTapCept.php)"</span> <span class="na">assertions=</span><span class="s">"2"</span> <span class="na">time=</span><span class="s">"2.459026"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;testcase</span> <span class="na">file=</span><span class="s">"Cli\RunWithXmlCept.php"</span> <span class="na">name=</span><span class="s">"check xml reports (Cli\RunWithXmlCept.php)"</span> <span class="na">assertions=</span><span class="s">"4"</span> <span class="na">time=</span><span class="s">"2.416413"</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;/testsuite&gt;</span>
<span class="nt">&lt;/testsuites&gt;</span></code></pre></figure>

<p>Currently this reports are not perfect as for different file formats and you may lack some important information. For this cases, please create issues on GitHub or in Q&amp;A section.</p>

<p>Thanks to Nikita Groshin new module for <a href="https://kohanaframework.org/">Kohana</a> Framework integration was added. Please, check it out for your Kohana projects and leave a feedback.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li><a href="https://github.com/Codeception/Codeception/issues/5">with new release of ZF2 bug with empty cookie parameter was fixed</a></li>
  <li><a href="https://github.com/Codeception/Codeception/issues/13">bootstrap was not loaded for Test files</a></li>
  <li><a href="https://github.com/Codeception/Codeception/issues/11">fails on generation of html reports</a></li>
</ul>

<p>Also there were some encoding issues, but they are solved easily if you make sure your code and site has a UTF-8 encoding.</p>

<p>Thanks again to all contributors and reporters.</p>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package.</p>

<p>Also you should update Mink, as it uses Zend Framework 2 beta 3 now for PHP browser. All Codeception dependencies can be updated with a single command.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept <span class="nb">install</span></code></pre></figure>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.5 Released.</title>
      <link>https://codeception.com/02-21-2012/se-release.html</link>
      <pubDate>Tue, 21 Feb 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-21-2012/se-release</guid>
      <description><![CDATA[ <p>Almost every week Codeception gets a new release. I think it’s quite good tempo. Every release contains not only bugfixes but a new features too.
I’m satisfied but today’s release, because all changes were made by new Codeception contributors. Thank you, guys!</p>

<h2 id="features">Features</h2>

<p>A new module for <a href="https://codeception.com/docs/modules/SocialEngine">Social Engine</a> was created by <a href="https://tvorzasp.com/">Artem Kovradin</a>. He took the code of Zend Framework module and adopted it for Social Engine, which is build with powered by Zend Framework. With now on, you can simply test you social networks built on top of Social Engine.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>Windows command line problem solved, thanks to <a href="https://github.com/Morf">Morf</a></li>
  <li>There were problem in functional tests for forms with no submits (‘&lt;input type=”submit”’). This bug was pointed by <a href="https://github.com/svsool">svsool</a>.</li>
</ul>

<p>Also there were some encoding issues, but they are solved easily if you make sure your code and site has a UTF-8 encoding.</p>

<p>Thanks again to all contributors and reporters.</p>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package.</p>

 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.4 Released. Behavior Driven Development.</title>
      <link>https://codeception.com/02-21-2012/bdd-release-1-0-4.html</link>
      <pubDate>Tue, 21 Feb 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-21-2012/bdd-release-1-0-4</guid>
      <description><![CDATA[ <p>This release brings a real behavior driven development to Codeception. Before that we talked about testing in BDD-style, but nothing about real development by behavior. There were just few changes made in code. More changes are coming to documentation.</p>

<h2 id="specifications">Specifications</h2>

<p>With Behavior Driven Development you start development of class by writing it’s specifications. Specifications are written as methods of Cest class and start with ‘should’ word.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>

<span class="kd">class</span> <span class="nc">EventMachineCest</span> <span class="p">{</span>

	<span class="nv">$class</span> <span class="o">=</span> <span class="s1">'EventMachine'</span><span class="p">;</span>
	
	<span class="k">function</span> <span class="n">shouldHaveInitialState</span><span class="p">()</span> <span class="p">{}</span>	
	<span class="k">function</span> <span class="n">shouldMoveBetweenTransitions</span><span class="p">()</span> <span class="p">{}</span>
	<span class="k">function</span> <span class="n">shouldMoveBetweenTransitionsOnCondition</span><span class="p">()</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The <em>EventMachine</em> class in example above is not written, but we’ve already defined what to expect from it. After a basic requirements are specified we can take a deeper look into it and describe how it should be used. From this point your specifications become a valid Codeception tests.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">EventMachineCest</span>  <span class="p">{</span>

	<span class="nv">$class</span> <span class="o">=</span> <span class="s1">'EventMachine'</span><span class="p">;</span>

   <span class="cd">/**
	* @doc getState
	*/</span>
	<span class="k">function</span> <span class="n">shouldHaveInitialState</span><span class="p">(</span><span class="kt">CodeGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="nv">$em</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">EventMachine</span><span class="p">;</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeMethod</span><span class="p">(</span><span class="nv">$em</span><span class="p">,</span> <span class="s1">'getState'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeResultEquals</span><span class="p">(</span><span class="s1">'initial'</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>For full EventMachineCest example see my <a href="https://gist.github.com/1862951">Gist on Github</a>.</p>

<p>Codeception generates a pretty good documentation with <a href="https://codeception.com/02-15-2012/unit-testing.html">DocBlox</a> based on your scenario. The @doc annotation marks that a getState method documentation will be updated by current test scenario.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">I want to have initial state

I execute method <span class="nv">$eventMachine</span>, <span class="s1">'getState'</span>
I see result equals <span class="s1">'initial'</span></code></pre></figure>

<h2 id="scenarios">Scenarios</h2>

<p>For making acceptnace tests usable for writing Stories we’ve added 2 new methods. It’s <em>am</em> and <em>lookForwardTo</em> which represent ‘As a …’ and ‘So that’ definitions from Story.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">();</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">am</span><span class="p">(</span><span class="s1">'regular site user'</span><span class="p">);</span> 		<span class="c1">// As a regular user</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create my blog page'</span><span class="p">);</span>  <span class="c1">// I want to create my blog page</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">lookForwardTo</span><span class="p">(</span><span class="s1">'get a cool blog here'</span><span class="p">);</span> 	<span class="c1">// So that I get a cool blog</span>

<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s2">"blog can't be created twice"</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s2">"blog has RSS feed"</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s2">"am administrator of this blog"</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>After that Cept can be extended in a valid Cept file. 
Refer to this <a href="https://gist.github.com/1844158">Gist demonstrates</a> for example.</p>

<h2 id="bugfixes">Bugfixes</h2>

<ul>
  <li>seeLink and dontSeeLink for acceptance tests were fixed. Thanks to <a href="https://github.com/kkamkou">
Kanstantsin Kamkou</a>.</li>
  <li>comments are displayed in output as well as actions.</li>
  <li>Selenium docs updated.</li>
</ul>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package.</p>

 ]]></description>
    </item>
    
    <item>
      <title>BDD Approach to Unit Testing with Codeception.</title>
      <link>https://codeception.com/02-15-2012/unit-testing.html</link>
      <pubDate>Wed, 15 Feb 2012 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-15-2012/unit-testing</guid>
      <description><![CDATA[ <p>Codeception is new BDD-style testing framework for PHP. It makes testing easier than it was before. Yep, really. If you are not a fan of testing, that might as well be because you haven’t used the proper tools. We’ve already showed you how simple it is to automate testing for any web application by writing <a href="https://codeception.com/01-20-2012/starting-acceptance.html">acceptance tests</a>. Today we will dig deeper into the code and show you how it can be tested.</p>

<p>With BDD approach in Codeception, any test, even the unit test, is written as a scenario. By this scenario you declare what you are doing and what results you expect to see. In traditional xUnit scheme your test is just a piece of code that uses the method being tested. This piece of code becomes a mess when you test complex units depending on other classes or when you need to check data in a database, etc. Codeception always keeps your unit tests simple and readable.</p>

<p>I always start with a model example in the MVC pattern. I am not using any of existing PHP ORMs in the sample code, and this will make the code look a little bit weird. I’m doing this just to demonstrate testing process.</p>

<p>Here we’ve got a sample model class.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">User</span> <span class="kd">extends</span> <span class="nc">AbstractModel</span> <span class="p">{</span>
	
	<span class="k">public</span> <span class="k">function</span> <span class="n">create</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">isNew</span><span class="p">)</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">ModelException</span><span class="p">(</span><span class="s2">"User already created"</span><span class="p">);</span>		
		<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="n">role</span><span class="p">)</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">role</span> <span class="o">=</span> <span class="s1">'member'</span><span class="p">;</span>

		<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">validate</span><span class="p">())</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">ValidationException</span><span class="p">(</span><span class="s2">"User is invalid"</span><span class="p">);</span>

		<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">save</span><span class="p">();</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Quite a complex method of ORM class, but its usage is really simple:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">User</span><span class="p">;</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">();</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>How is this method tested with Codeception? First of all, we won’t be testing any inherited methods like <em>validate</em> or <em>save</em>. They belong to AbstractModel class and are to be tested there. The ‘create’ method is to be tested in full isolation. For this we will not use the actual User class, but its Stub, i.e. a class with some methods replaced by their dummies.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>

<span class="kn">use</span> <span class="nc">Codeception\Util\Stub</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">UserCest</span> <span class="p">{</span>

	<span class="k">public</span> <span class="nv">$class</span> <span class="o">=</span> <span class="s1">'User'</span><span class="p">;</span>
	
	<span class="k">public</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="kt">CodeGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>		
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create new user by name'</span><span class="p">);</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveStub</span><span class="p">(</span><span class="nv">$user</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmptyExcept</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="s1">'create'</span><span class="p">));</span>

		<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'user is validated and saved'</span><span class="p">)</span>		
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'validate'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'save'</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Here we have tested that the ‘validate’ and ‘save’ methods were actually invoked. We assume that ‘validate’ and ‘save’ are themselves tested; thus, they will work as expected. And if the test fails, we know the source of problem is the ‘create’ method itself.</p>

<p>However, the test doesn’t cover exceptions that may be thrown. Thus let’s improve it by making the validate method simulate exceptions.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kn">use</span> <span class="nc">Codeception\Util\Stub</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">UserCest</span> <span class="p">{</span>

	<span class="k">public</span> <span class="nv">$class</span> <span class="o">=</span> <span class="s1">'User'</span><span class="p">;</span>
	
	<span class="k">public</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="kt">CodeGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>		
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create new user by name'</span><span class="p">);</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveStub</span><span class="p">(</span><span class="nv">$user</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmptyExcept</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="s1">'create'</span><span class="p">));</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveStub</span><span class="p">(</span><span class="nv">$invalid_user</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmptyExcept</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="s1">'create'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
			<span class="s1">'validate'</span> <span class="o">=&gt;</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span> <span class="p">}</span>
		<span class="p">)));</span>		

		<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'user is validated and saved'</span><span class="p">)</span>		
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'validate'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'save'</span><span class="p">);</span>
		
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'exception is thrown for invalid user'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$invalid_user</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeExceptionThrown</span><span class="p">(</span><span class="s1">'ValidationException'</span><span class="p">,</span><span class="s1">'User is invalid'</span><span class="p">);</span>				
			
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'exception is thrown while trying to create not new user'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">changeProperty</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span><span class="s1">'isNew'</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$user</span><span class="p">)</span>						
			<span class="o">-&gt;</span><span class="nf">seeExceptionThrown</span><span class="p">(</span><span class="s1">'ModelException'</span><span class="p">,</span> <span class="s2">"User already created"</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The only thing we haven’t cover in the test is user’s default role assertion. In case we store all column values as public variables, we can use the ‘seePropertyEquals’ method.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>

<span class="kn">use</span> <span class="nc">Codeception\Util\Stub</span><span class="p">;</span>

<span class="kd">class</span> <span class="nc">UserCest</span> <span class="p">{</span>

	<span class="k">public</span> <span class="nv">$class</span> <span class="o">=</span> <span class="s1">'User'</span><span class="p">;</span>
	
	<span class="k">public</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="kt">CodeGuy</span> <span class="nv">$I</span><span class="p">)</span>
	<span class="p">{</span>		
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create new user by name'</span><span class="p">);</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveStub</span><span class="p">(</span><span class="nv">$user</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmptyExcept</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="s1">'create'</span><span class="p">));</span>
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">haveStub</span><span class="p">(</span><span class="nv">$invalid_user</span> <span class="o">=</span> <span class="nc">Stub</span><span class="o">::</span><span class="nf">makeEmptyExcept</span><span class="p">(</span><span class="s1">'User'</span><span class="p">,</span> <span class="s1">'create'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
			<span class="s1">'validate'</span> <span class="o">=&gt;</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"invalid"</span><span class="p">);</span> <span class="p">}</span>
		<span class="p">)));</span>		

		<span class="nv">$user</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="s1">'davert'</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>

		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'user is validated and saved'</span><span class="p">)</span>	
			<span class="o">-&gt;</span><span class="nf">seePropertyEquals</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'role'</span><span class="p">,</span> <span class="s1">'member'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'validate'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeMethodInvoked</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span> <span class="s1">'save'</span><span class="p">);</span>
	
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'exception is thrown for invalid user'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$invalid_user</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">seeExceptionThrown</span><span class="p">(</span><span class="s1">'ValidationException'</span><span class="p">,</span><span class="s1">'User is invalid'</span><span class="p">);</span>				
			
		<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">expect</span><span class="p">(</span><span class="s1">'exception is thrown while trying to create not new user'</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">changeProperty</span><span class="p">(</span><span class="nv">$user</span><span class="p">,</span><span class="s1">'isNew'</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span>
			<span class="o">-&gt;</span><span class="nf">executeTestedMethodOn</span><span class="p">(</span><span class="nv">$user</span><span class="p">)</span>						
			<span class="o">-&gt;</span><span class="nf">seeExceptionThrown</span><span class="p">(</span><span class="s1">'ModelException'</span><span class="p">,</span> <span class="s2">"User already created"</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>By this test we have 100% covered the ‘create’ method with test and isolated its environment. As a bonus, we can improve our documentation by the text of this scenario. If we use <a href="https://codeception.com/02-14-2012/generators-release-1-0-3.html">DocBlox, we can set up Codeception plugin</a> and generate documentation for User class ‘create’ method.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">With this method I can create new users by name.

Declared Variables:
* $user1 (User)
* $user2 (User)

If I execute $user1-&gt;create()

I expect user is validated and saved
I will see property equals $user1, 'role', 'member'
I will see method invoked $user1, 'validate'
I will see method invoked $user1, 'save'

I expect exception is thrown for invalid user
If I execute $user2-&gt;create()
I will see exception thrown 'ValidationException', 'invalid'

I expect exception is thrown while trying to create not new user
I change property $user1, 'isNew', false
If I execute $user1-&gt;create()
I will see exeception thrown 'ModelException', 'User already created'</code></pre></figure>

<p>We can say that the ‘create’ method is fully described by this text.</p>

<h2 id="conclusion">Conclusion</h2>

<p>What we’ve got by writing the test for the <em>create</em> method of user class? We’ve made sure that by using this method the user is always validated and saved when created. We’ve also made sure the default role is ‘member’. Well, that’s all. But that’s all that ‘create’ function is doing.</p>

<p>For further reading on Codeception unit tests see our <a href="https://codeception.com/docs/07-UnitTestsPractice">documentation</a>.</p>

<p>In the next post we will simplify the model test by breaking some isolation rules. Subscribe to our <a href="https://codeception.com/rss.xml">RSS</a> channel to stay in touch.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.3 Released. Generators and Agile Documentation.</title>
      <link>https://codeception.com/02-14-2012/generators-release-1-0-3.html</link>
      <pubDate>Tue, 14 Feb 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-14-2012/generators-release-1-0-3</guid>
      <description><![CDATA[ <p>This <em>Codeception</em> release is all about minor but useful features. Starting from 1.0.3 you will be notified on every new Codeception release from console. 
If you are not running tests, Codeception Cli application will check for new version and notify you if it is available.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept
UPDATE: version 1.0.3 released. See changes on: https://codeception.com.
Codeception version 1.0.2</code></pre></figure>

<p>There are new generators for empty tests: <em>Cest</em> and <em>Cept</em> files. Empty test suite can be generated too. Just check new <strong>‘generate:’</strong> commands.</p>

<h3 id="agile-documentation">Agile Documentation</h3>

<p>But the most interesting  generation feature is <strong>Agile Documentation</strong>. From now you can improve your documentation generated by <a href="https://www.docblox-project.org/">DocBlox</a> by appending test scenarios into text. With Codeception BDD approach to <a href="https://codeception.com/docs/06-UnitTestsAndBDD">Unit Tests</a> it’s easy to imagine every test as usage documentation.</p>

<p>The concept of Agile Documentation will be demonstrated in following example:</p>

<p>We have a sample static method for creating an entity Group. Which can be group of people in social network, for example.
This method uses Doctrine 2 as ORM.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="kd">class</span> <span class="nc">Group</span> <span class="p">{</span>
	
	<span class="c1">// This creates new group by user</span>
	<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="nv">$name</span><span class="p">,</span> <span class="nv">$founder_id</span><span class="p">)</span>
	<span class="p">{</span>		
		<span class="nv">$em</span> <span class="o">=</span> <span class="k">self</span><span class="o">::</span><span class="nv">$entityManager</span><span class="p">;</span>

		<span class="nv">$group</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nc">Model\Group</span><span class="p">;</span>
		<span class="nv">$group</span><span class="o">-&gt;</span><span class="nf">setName</span><span class="p">(</span><span class="nv">$name</span><span class="p">);</span>
		<span class="nv">$group</span><span class="o">-&gt;</span><span class="nf">setUser</span><span class="p">(</span><span class="nv">$em</span><span class="o">-&gt;</span><span class="nf">getRepository</span><span class="p">(</span><span class="s1">'Model\User'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">find</span><span class="p">(</span><span class="nv">$founder_id</span><span class="p">));</span>
		<span class="nv">$em</span><span class="o">-&gt;</span><span class="nf">persist</span><span class="p">(</span><span class="nv">$group</span><span class="p">);</span>
		<span class="nv">$em</span><span class="o">-&gt;</span><span class="nb">flush</span><span class="p">();</span>

		<span class="k">return</span> <span class="nv">$group</span><span class="o">-&gt;</span><span class="nf">getId</span><span class="p">();</span>
	<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>This method requires Id of user who creates group and group name. Here is test for this function:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">create</span><span class="p">(</span><span class="err">\</span><span class="nc">CodeGuy</span> <span class="nv">$I</span><span class="p">)</span>
    <span class="p">{</span>
    	<span class="nv">$user_id</span> <span class="o">=</span> <span class="nc">Fixtures</span><span class="o">::</span><span class="nf">get</span><span class="p">(</span><span class="s1">'valid_user'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">getId</span><span class="p">();</span>

        <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create group'</span><span class="p">);</span>
        <span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">executeTestedMethodWith</span><span class="p">(</span><span class="s1">'DemoGroup'</span><span class="p">,</span> <span class="nv">$user_id</span><span class="p">)</span>
            <span class="o">-&gt;</span><span class="nf">seeInRepository</span><span class="p">(</span><span class="s1">'Model\Group'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'name'</span> <span class="o">=&gt;</span> <span class="s1">'DemoGroup'</span><span class="p">,</span> <span class="s1">'user_id'</span> <span class="o">=&gt;</span> <span class="nv">$user_id</span><span class="p">,</span> <span class="s1">'type'</span> <span class="o">=&gt;</span> <span class="s1">'group'</span><span class="p">))</span>
            <span class="o">-&gt;</span><span class="nf">seeResultIs</span><span class="p">(</span><span class="s1">'int'</span><span class="p">);</span>
    <span class="p">}</span>
<span class="cp">?&gt;</span>    </code></pre></figure>

<p>This test is translated into documentation for Group::create method.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">With this method I can create group

If I execute <span class="se">\S</span>ervice<span class="se">\G</span>roup::create<span class="o">(</span><span class="s2">"DemoGroup"</span>,1<span class="o">)</span>
I will see <span class="k">in </span>repository <span class="s2">"Model</span><span class="se">\G</span><span class="s2">roup"</span>,<span class="o">{</span><span class="s2">"name"</span>:<span class="s2">"DemoGroup"</span>,<span class="s2">"user_id"</span>: 1, <span class="s2">"type"</span>: <span class="s2">"group"</span> <span class="o">}</span>
I will see result is <span class="s2">"int"</span></code></pre></figure>

<p>Codeception scans for all Cest files and for all classes passed to DocBlox. When tests match the function in documentation the test is processed and appended into function description.</p>

<p>To start using Codeception with DocBlox you should use the same project root for both projects, i.e. codeception.yml and docblox.xml should be in one directory.
Include plugin into docblox.xml:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">    <span class="nt">&lt;plugins&gt;</span>
        <span class="nt">&lt;plugin</span> <span class="na">path=</span><span class="s">"{FULL-PATH-TO-PEAR}/Codeception/plugins/DocBlox/Codeception"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;/plugin&gt;</span>
    <span class="nt">&lt;/plugins&gt;</span></code></pre></figure>

<p>As you see, you should specify path to PEAR explicitly. This is DocBlox limitation. Plugins can be either local or provided with DocBlox distribution. I’m not sure how to deal with current Codeception plugin for DocBlox, so I <a href="https://github.com/docblox/docblox/issues/370">asked this question on GitHub</a>. I hope in near future a better solution will be proposed.</p>

<h3 id="bugfixes">Bugfixes</h3>

<ul>
  <li>replaced suppressed errors with error elimination (thanks to <a href="https://github.com/jonphipps">jonphipps</a>)</li>
  <li>fixed scenario generations</li>
  <li>fixed generation of html reports</li>
</ul>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Codeception 1.0.2 Released.</title>
      <link>https://codeception.com/02-05-2012/minor-release-1-0-2.html</link>
      <pubDate>Sun, 05 Feb 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/02-05-2012/minor-release-1-0-2</guid>
      <description><![CDATA[ <p>As you may know, <strong>Codeception a BDD-style testing framework</strong> has tools for cleaning up tested database between tests.
This week tools for database repopulation in Codeception were improved and it’s usage was covered in <a href="https://codeception.com/docs/08-Data">new chapter of Guides</a>. To get your database populated before tests, just provide an SQL dump and set up PDO connection. For functional and unit testing best way to clean up your database faster is not to pollute it at all. All database queries can be taken into transaction and rolled back at test end. This behavior is introduced within new <a href="https://codeception.com/docs/modules/Dbh">Dbh</a> module, and in ORM modules for Doctrine1 and Doctrine2. To speed up data repopulation in acceptance tests we recommend you to move database to SQLite.</p>

<p>Database repopulation is the subject of the new Guide: <a href="https://codeception.com/docs/08-Data">Working with Data</a> was started. It explains different strategies for database cleanups and usage of fixtures in Codeception.</p>

<p>Codeception is now tested for loading and cleaning up SQLite, MySQL, and PostgreSQL dumps.</p>

<h4 id="bugfixes">Bugfixes:</h4>

<ul>
  <li>configuration merged improperly (reported and fixed by zzmaster).</li>
  <li>steps are printed in realtime and not buffered anymore.</li>
  <li>asserts on html pages doesn’t echo all page texts for strings longer then 500 chars.</li>
  <li>tests are sorted by name when loading.</li>
</ul>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Behavior Driven Testing with Zend Framework</title>
      <link>https://codeception.com/01-27-2012/bdd-with-zend-framework.html</link>
      <pubDate>Fri, 27 Jan 2012 22:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-27-2012/bdd-with-zend-framework</guid>
      <description><![CDATA[ <p>Codeception is testing framework in which all tests are written in a single descriptive manner. 
It’s aim is to make tests easy to read, easy to write and easy to debug. Every single test you write can be run either in Selenium, in PHP Browser emulator, or as a functional test for <strong>Zend Framework</strong>. Today we will look how Codeception can be used for testing your Zend application.</p>

<p>Most of CRUD applications use forms for creating or editing content. It’s hard to test every form on site after each release manually. But we will automate this process. For testing Zend applications you probably used it’s <a href="https://framework.zend.com/manual/1.11/en/zend.test.phpunit.html">Zend_Test_PHPUnit</a> class, which is build on top of PHPUnit’s TestCase. Codeception is built on top of PHPUnit too. And takes similar approaches from <strong>Zend_Test_PHPUnit_ControllerTestCase</strong>. But commands available in tests being made intuitively simple and much more human friendly then they are in Zend_Test_PHPUnit.</p>

<p>We take a code from Zend_Test_PHPUnit tutorial:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// Zend_Test_PHPUnit</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">request</span><span class="o">-&gt;</span><span class="nf">setMethod</span><span class="p">(</span><span class="s1">'POST'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">setPost</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
<span class="s1">'username'</span> <span class="o">=&gt;</span> <span class="s1">'foobar'</span><span class="p">,</span>
<span class="s1">'password'</span> <span class="o">=&gt;</span> <span class="s1">'foobar'</span>
<span class="p">));</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">dispatch</span><span class="p">(</span><span class="s1">'/user/login'</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertRedirectTo</span><span class="p">(</span><span class="s1">'/user/view'</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">resetRequest</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">resetResponse</span><span class="p">();</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="n">request</span><span class="o">-&gt;</span><span class="nf">setMethod</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">setPost</span><span class="p">(</span><span class="k">array</span><span class="p">());</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">dispatch</span><span class="p">(</span><span class="s1">'/user/view'</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertQueryContentContains</span><span class="p">(</span><span class="s1">'h2'</span><span class="p">,</span> <span class="s1">'User: foobar'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>and reproducing it for Codeception:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="c1">// Codeception</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">submitForm</span><span class="p">(</span><span class="s1">'form#loginForm'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'username'</span> <span class="o">=&gt;</span> <span class="s1">'foobar'</span><span class="p">,</span> <span class="s1">'password'</span> <span class="o">=&gt;</span> <span class="s1">'foobar'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">seeInCurrentUrl</span><span class="p">(</span><span class="s1">'/user/view'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'User: foobar'</span><span class="p">,</span> <span class="s1">'h2'</span><span class="p">);</span>
<span class="cp">?&gt;</span> </code></pre></figure>

<p>It’s only 4 lines long, but it does the same as the test above. It tests logging in on site, nothing more, nothing less. We can expect user is logged in if he was moved from ‘/user’ page, to ‘/user/view’ and username is in Heading2 element of that page.</p>

<p>Codeception won’t perform asserts for application internals as module/controller/action, as this is not natural to bound functionality into one place. A small refactoring will completely break a test, even if application is running perfectly. For the same reasons Codeception doesn’t provide analog for <em>assertQueryCount</em> or <em>assertQuery</em>, because they test a markup probably unseen to user. If a element on page has changed a test will fail, still application can work perfectly. We are testing only elements user can interact with and user can see. This makes tests more stable and drives us to less false negative results.</p>

<p>All the <em>assertXXXX</em> commands is replaced with natural ‘see’ commands.</p>

<ul>
  <li><strong>see</strong> - checks if text or element with text is on page</li>
  <li><strong>seeInCurrentUrl</strong> - checks if a url contains specified value</li>
  <li><strong>seeLink</strong> - checks link exist on page</li>
  <li><strong>seeInField</strong></li>
  <li><strong>seeCheckboxIsChecked</strong></li>
  <li>etc…</li>
</ul>

<p>This commands can accept either CSS locators or element names.</p>

<p>With Codeception you can write tests that will be executed inside a Zend Framework, but will simulate user actions with less technical code. 
As every test should be readable and thus simple definitions in terms “I do that”, “I see this” are better to understand. Especially, if a test is read by new developer.</p>

<p>Today we are going to write tests for open source blog application <a href="https://github.com/frogprincess/Lilypad-Zend-Framework-Blog">Lilypad-Zend-Framework-Blog</a>. We assume you already have Zend Framework intalled.</p>

<p>It can be taken from GitHub:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">git clone git://github.com/Codeception/ZFBlog.git</code></pre></figure>

<p>Set up database and configure <em>application/configs/application.ini</em> to access it. Default settings are:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">resources.db.adapter <span class="o">=</span> <span class="s2">"PDO_MYSQL"</span>
resources.db.params.host <span class="o">=</span> <span class="s2">"localhost"</span>
resources.db.params.username <span class="o">=</span> <span class="s2">"root"</span>
resources.db.params.password <span class="o">=</span> <span class="s2">""</span>
resources.db.params.dbname <span class="o">=</span> <span class="s2">"zfblog"</span></code></pre></figure>

<p>Database should be populated with <em>zend_blog.sql</em> dump from the project root.</p>

<p>To start covering it with tests <a href="https://codeception.com/install">Codeception should be installed</a>.</p>

<p>Run bootstrap command from root of ZFBlog:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept bootstrap
<span class="nv">$ </span>codecept build</code></pre></figure>

<p>This will create a default test suites. Now some steps for configuration should be done.</p>

<p>For interacting with Zend Framework a <a href="https://codeception.com/docs/modules/ZF1">ZF1</a> module is used.
It should be enabled in functional tests configuration: <em>tests/functional.suite.yml</em>.
For database repopulation after each step add <a href="https://codeception.com/docs/modules/Db">Db</a> module too.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">class_name</span><span class="pi">:</span> <span class="s">TestGuy</span>
<span class="na">modules</span><span class="pi">:</span>
<span class="err">	</span><span class="na">enabled</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">ZF1</span><span class="pi">,</span> <span class="nv">Db</span><span class="pi">,</span> <span class="nv">TestHelper</span><span class="pi">]</span></code></pre></figure>

<p>We use default settings for ZF1 module to connect to ZFBlog application. We use <em>‘testing’</em> environment and <em>‘application.ini’</em> stored in it’s standard place: ‘application/configs/application.ini’. But Db module requires additional configuration. We need schema and default data was recreated for each test run. We have database dump, a file named <em>zend_blog.sql</em> in root of project. We should point Codeception to use it for database repopulation. Now update a <em>codeption.yml</em> config in project’s root and set proper db credentials.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">paths:
    tests: tests
    log: tests/_log
    data: tests/_data
    helpers: tests/_helpers
settings:
    bootstrap: _bootstrap.php
    suite_class: <span class="se">\P</span>HPUnit_Framework_TestSuite
    colors: <span class="nb">true
    </span>memory_limit: 1024M
    log: <span class="nb">true
</span>modules:
    config:
        Db:
            dsn: <span class="s1">'mysql:host=localhost;dbname=zfblog'</span>
            user: <span class="s1">'root'</span>
            password: <span class="s1">''</span>
            dump: zend_blog.sql</code></pre></figure>

<p>We configured Db credentials and database dump being used. Now let’s write some tests. In <em>tests/functional</em> let’s create file <em>CreateBlogCept.php</em>:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TestGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create new blog post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/admin'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Blog Editing'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Add new blog'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Add new blog'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Now a test can be run with command.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept run functional</code></pre></figure>

<p>And here is the expected result.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Codeception PHP Testing Framework v1.0.1
Powered by PHPUnit 3.6.4 by Sebastian Bergmann.

Suite functional started
Trying to  create new blog post <span class="o">(</span>CreateBlogCept.php<span class="o">)</span> - Ok


Time: 2 seconds, Memory: 21.00Mb

OK <span class="o">(</span>1 <span class="nb">test</span>, 2 assertions<span class="o">)</span></code></pre></figure>

<p>To get detailed information of what steps were taken in test, run this command with –steps option. And this is what will be printed:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Trying to  create new blog post <span class="o">(</span>CreateBlogCept.php<span class="o">)</span>
Scenario:
<span class="k">*</span> I am on page <span class="s2">"/admin"</span>
<span class="k">*</span> I see <span class="s2">"Blog Editing"</span>
<span class="k">*</span> I click <span class="s2">"Add new blog"</span>
<span class="k">*</span> I see <span class="s2">"Add new blog"</span>
  OK</code></pre></figure>

<p>Also, all executed tests, steps performed and a results of execution, will be written to ‘tests/_log’ directory.</p>

<p>Try to create your own test for editing post. I hope you will like new way of testing Zend Application. Use Codeception to make your applications stable and predictable.</p>

<p>Support for Zend2 is coming soon.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Released 1.0.1. Please update</title>
      <link>https://codeception.com/01-26-2012/bugfix-release.html</link>
      <pubDate>Thu, 26 Jan 2012 01:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-26-2012/bugfix-release</guid>
      <description><![CDATA[ <p>This relese fixes two reported bugs.</p>

<ul>
  <li>using <strong>see</strong> commands on pages with &lt;!DOCTYPE</li>
  <li>using <strong>see</strong> commands with non-latin characters. PhpBrowser, Selenium, Frameworks modules were updated.</li>
</ul>

<p>Please update your version via PEAR:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>pear <span class="nb">install </span>codeception/Codeception</code></pre></figure>

<p>or download updated Phar package. It’s important to update Codeception now.</p>

<p>In next releases an automatic updater will be added.</p>
 ]]></description>
    </item>
    
    <item>
      <title>Introduction to Codeception</title>
      <link>https://codeception.com/01-20-2012/starting-acceptance.html</link>
      <pubDate>Fri, 20 Jan 2012 20:03:50 +0000</pubDate>
      <author>codeception@davert.mail.ua (Michael Bodnarchuk)</author>
      <guid>https://codeception.com/01-20-2012/starting-acceptance</guid>
      <description><![CDATA[ <p>We build web sites with PHP, we build web services and web applications. But is PHP good enough for testing them?</p>

<p>How often do you see PHP projects with no line of test written? From my experience, this situation happens quite often. We should state the unpleasant fact that tests are not so popular around the PHP world. Surely, the advanced developers with 5+ years of experience in PHP and other programming languages understand importance of testing and PHPUnit usage. But juniors and seniors are just skipping testing and, therefore, produce unstable web applications.</p>

<p>From my point of view, the key issue is not in developers themselves. They are pretty good and skilled. But it is PHP that lacks the tools for testing. If you write a site and you want to test its behavior, what is the natural way to do so? Selenium? PHPUnit + Selenium? This tools are powerful, but too complex. Using them is like using a sledgehammer to crack a nut.</p>

<p>For the last two months I have been developing a simple, yet powerful alternative testing framework: Codeception. It focuses on making tests easy to read, easy to write and easy to debug. This code illustrates a common acceptance test in Codeception:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'create new blog post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/blog/posts'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Create new post'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Title'</span><span class="p">,</span><span class="s1">'Codeception, a new way of testing!'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Text'</span><span class="p">,</span><span class="s1">'Codeception is new PHP full-stack testing framework.'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Send'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Congratulations, your post is successfully created!'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>It’s pretty clear, isn’t it? But here goes another feature of Codeception: this code can be executed as a functional test in symfony, Symfony2, Zend Framework, with PHP web scrapper Goutte, or even with Selenium!</p>

<p>Codeception is all about behavior-driven testing. For each part of application you describe user actions and the results you are expecting them to see. Users interact with your web application through a web browser. They open the page, click on links, fill the forms, and in the end they see the site has generated a proper result in response. In Codeception you record user’s steps and make testing engine reproduce them. You need a web server running to perform requests through a web browser.</p>

<p>Writing tests is just about choosing actions from a list and injecting proper parameters.
<img src="https://dl.dropbox.com/u/930833/codecept.png" alt="IDE autocomplition demo" /></p>

<p>If you are ready to start writing first Codeception test, just follow the <a href="https://codeception.com/install">installation steps</a>.
After you install package and its dependencies, select a project you want to test (I suppose you have one) and run a bootstrap command in its root:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept bootstrap</code></pre></figure>

<p>It creates a ‘tests’ directory with 3 default testing suites:</p>

<ul>
  <li>acceptance</li>
  <li>functional</li>
  <li>unit</li>
</ul>

<p>Let’s start with the sample acceptance test. We shall save it into ‘tests/acceptance/StartPageCept.php’.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantToTest</span><span class="p">(</span><span class="s1">'front page of my site'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'A sample text on my site'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Replace ‘A sample text on my site’ with the text that actually is on your site.
To make it run we should start a local web server with the tested application. 
The URL of this application should be specified in suite configuration file: ‘tests/acceptance.suite.yml’.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">    config:
        PhpBrowser:
            url: <span class="s1">'here goes url'</span></code></pre></figure>

<p>Now a test can be executed with the command <em>run</em>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>codecept run acceptance</code></pre></figure>

<p>Then the result is shown:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Suite acceptance started
Trying to see front page of my site <span class="o">(</span>StartPageCept<span class="o">)</span> - Ok

Time: 1 second, Memory: 21.00Mb

OK <span class="o">(</span>1 <span class="nb">test</span>, 1 assertions<span class="o">)</span></code></pre></figure>

<p>Now let’s see how forms can be tested. Perhaps the most often used forms are login forms.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'log in as regular user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Username'</span><span class="p">,</span><span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'Password'</span><span class="p">,</span><span class="s1">'qwerty'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'Login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello, davert'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>The ‘fillField’ and ‘click’ command take element name or CSS selector as paramater. Thus, if you don’t use labels for fields, you can rewrite this scenario in the following way:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'log in as regular user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'form#login input[name=login]'</span><span class="p">,</span><span class="s1">'davert'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">fillField</span><span class="p">(</span><span class="s1">'form#login input[name=password]'</span><span class="p">,</span><span class="s1">'qwerty'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">click</span><span class="p">(</span><span class="s1">'form#login input[type=submit]'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello, davert'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>Or this can be shortened to a single command:</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp">&lt;?php</span>
<span class="nv">$I</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">WebGuy</span><span class="p">(</span><span class="nv">$scenario</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">wantTo</span><span class="p">(</span><span class="s1">'log in as regular user'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">amOnPage</span><span class="p">(</span><span class="s1">'/login'</span><span class="p">);</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">submitForm</span><span class="p">(</span><span class="s1">'form#login'</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'login'</span> <span class="o">=&gt;</span> <span class="s1">'davert'</span><span class="p">,</span> <span class="s1">'password'</span> <span class="o">=&gt;</span> <span class="s1">'qwerty'</span><span class="p">));</span>
<span class="nv">$I</span><span class="o">-&gt;</span><span class="nf">see</span><span class="p">(</span><span class="s1">'Hello, davert'</span><span class="p">);</span>
<span class="cp">?&gt;</span></code></pre></figure>

<p>As you can see, tests in Codeception look pretty simple and compact. Testing environment is prepared out of the box, no need for the bootstrap code to be written. 
You can compare Codeception to Behat, to PHP DSL, but Codeception can do much more than executing scenarios. As you’ve already seen, it’s not limited to acceptance tests only.</p>

<p>Codeception is fully documented, look into the guides for full reference.
Codeception is in beta-version, but it will evolve. Use it. Test your applications. Make them stable.</p>

<p>Next time functional tests will be covered.</p>
 ]]></description>
    </item>
    
  </channel> 
</rss>