Archív

Archív pro

OpenMeeting 24.9. na téma Testování webových aplikací

24.09.2009 View Comments

Dnes se konal OpenMeeting na téma Testování webových aplikací.

První přednášku měl Michal Špaček ze Skypu o systému Selenium. Pokud jste viděli jeho přednášku na webExpu 2008 tak to bylo totéž v kratší variantě.

Druhá přednáška byla na téma opět Selenium a měl ji Filip Braun z Benety, ukazoval testování jak je dělají oni.

Do třetice také Selenium a to ukazoval Jakub Vrána na Adminerovi. Adminer je z velké části pokryt testy z hlediska funkčnosti. Jakub si měří pokrytí napříč aplikací (coverage) na co má vlastní skript, který mu to přehledně vyhodnocuje. Zazněla tady dobrá rada, pokud používáte Selenium RC v Internet Exploreru, vyvarujte se xpath výrazům a používejte CSS selektory, ušetříte tím hromadu času.

Čtvrtá přednáška od Karla Minaříka na téma Cucumber a testování v Ruby světe. Cucumber má velmi pěkný styl testů, které se dají psát například i česky a jazykem blízkým normálnímu člověku. Není omezeny jen na Ruby a měl by jít využít i pro další platformy. Určitě to brzo vyzkouším na php. Cucumber používá HTTP adaptér webrat pomocí, kterého se připojíte na Selenium nebo další nástroje (např. pro testování Flexu).

Pátá přednáška byla od Štěpána Bechyňského z Microsoftu. Ukazoval nám jak můžete testovat v prostředí Visual Studia 2008. Pokud chcete nějak testovat dobře aplikace v Internet Exploreru, přijde mi to jako jediná spolehlivá cesta. V novém Visual Studiu 2010 by to mělo být značně ještě vylepšeno.

Poslední přednáška od Vratislava Sejka z Unicornu se věnovala Bezpečnostnímu testování. Unicorn kromě funkčních a výkonových testů také dělá bezpečnostní testy na které se dá dobře využít nástroj IBM Rational AppScaner. Komplexní komerční nástroj, pokud někdo znáte nějaký dobrý podobný open source nástroj, prosím zmiňte ho do komentářů.

To je v souhrnu všechno co bylo obsahem formální části a potom samozřejmě probíhala už neformální diskuse jak to pravidelně bývá.

Categories: openmeeting Tags: ,

IE 8 bug s cookie a doménou jobs.cz

14.09.2009 View Comments

V práci jsme se setkali se zajímavým problémem, který se vyskytuje ojediněle, ale zato postihuje jen určitou doménu. Máme problém s Microsoft Internet Explorerem 8 a doménou jobs.cz.

IE8 odmítá nastavit cookies na doménu druhé úrovně. Nefunguje to pouze a jen pro jobs.cz, pro všechny jiné domény je to v pořádku. Je to záhada, kterou nebude jednoduché vyřešit.

Fungují všechny starší verze MS IE i všechny ostatní prohlížeče i všechny jiné domény druhé úrovně, které jsme zkusili. Nefunguje zápis serverový ani klientský. Cookies na domény třetí úrovně (www.jobs.cz apod.) rovněž bez problémů.

Zkušební skript může vypadat takto:

<?php
//if (strpos($_SERVER["HOST_NAME"], "jobs.cz") !== false) {
setcookie("jobsServerFull", "server", 0, "/");
setcookie("jobsServer2ndA", "server", 0, "/", ".jobs.cz");
setcookie("jobsServer2ndB", "server", 0, "/", "jobs.cz");
setcookie("jopsServerFull", "server", 0, "/");
setcookie("jopsServer2ndA", "server", 0, "/", ".jops.cz");
setcookie("jopsServer2ndB", "server", 0, "/", "jops.cz");
?>
<html>
<head>
<title>cookie test</title>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo/yahoo-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/cookie/cookie-min.js"></script>
</head>
<body>
<script type="text/javascript">
YAHOO.util.Cookie.set("jobsClientFull", "client", { path: "/"});
YAHOO.util.Cookie.set("jobsClient2ndA", "client", { path: "/", domain: ".jobs.cz" });
YAHOO.util.Cookie.set("jobsClient2ndB", "client", { path: "/", domain: "jobs.cz" });
YAHOO.util.Cookie.set("jopsClientFull", "client", { path: "/"});
YAHOO.util.Cookie.set("jopsClient2ndA", "client", { path: "/", domain: ".jops.cz" });
YAHOO.util.Cookie.set("jopsClient2ndB", "client", { path: "/", domain: "jops.cz" });
</script>

<h2>Cookies obtained</h2>
<xmp>
<?php var_dump($_COOKIE); ?>
</xmp>
</body>
</html>

nebo v jednodušší podobě

<?php
setcookie("serverTestCookie", "server", 0, "/", ".jobs.cz");
?>
<html>
<head>
<title>cookie test</title>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo/yahoo-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/cookie/cookie-min.js"></script>
</head>
<body>
<script type="text/javascript">
YAHOO.util.Cookie.set("clientTestCookie", "client", { path: "/", domain: ".jobs.cz" });
</script>

<h2>Cookies obtained</h2>
<xmp>
<?php var_dump($_COOKIE); ?>
</xmp>
</body>
</html>

příslušní virtualní host si na lokálním počítači nastavím třeba takto

<VirtualHost *:80>
DocumentRoot /srv/cookie
ServerName jobs.cz
ServerAlias www.jobs.cz jobs.cz jops.cz www.jops.cz
</VirtualHost>

a k tomu nějakého hosta

127.0.0.1    wwww.jobs.cz jobs.cz www.jops.cz jops.cz

Po prvním načtení bude kolekce cookies samozřejmě prázdná, ale už po tom druhem jsou v IE8 nastaveny pouze cookies na doménu třetí úrovně, druhé nic.

Závěr

Problém zřejmě souvisí s implementaci prohlížečích viz (1, 2). V TLD existuje .jobs a proto se dá usuzovat, že k ní IE8 chová nějak jinak. Ale proč to nepostihuje např. travel.cz, museum.cz info.cz je záhadou. Zatím to vypadá na chybu v IE8, která nám opravdu hodně znepříjemňuje život.

Všichni si to můžete vyzkoušet na http://lmc.jobs.cz/cookie.php.

Udělejte refresh stránky a dostanete tento výsledek kromě MS IE8, proboha proč?

cookie_test_ok

cookie_test_fail

Pokud by byl někdo schopný pomoci s nápravou této chyby budeme vděční za pomoc.

Aktualizace:
Pokud si dáte v Internet Exploreru res://urlmon.dll/ietldlist.xml dostanete se k blokovaným TLD doménám. Bohužel na něm je z ČR i jobs.cz.

Categories: microsoft Tags: ,

Česká verze pluginů pro WordPress

12.09.2009 View Comments

Co k tomu potřebujete?

Jak se to dělá

Pokud nejste zběhlý s programováním, tak asi to může být pro vás problém a proto jsem také napsal tento článek, třeba vám to pomůže pokud budete chtít něco takového dělat.

Když si stáhnete plugin WP-RecentComments na disk, rozbalíte ho někam do adresáře uvidíte tuto strukturu:

drwxr-xr-x 2 abtris 4.0K 2009-09-12 21:14 avatars
-rw-r--r-- 1 abtris  18K 2009-09-12 21:14 core.php(
drwxr-xr-x 2 abtris 4.0K 2009-09-12 21:14 css
drwxr-xr-x 2 abtris 4.0K 2009-09-12 21:14 js
drwxr-xr-x 2 abtris 4.0K 2009-09-12 21:28 languages
-rw-r--r-- 1 abtris  12K 2009-09-12 21:14 README.txt
-rw-r--r-- 1 abtris 8.6K 2009-09-12 21:14 screenshot-1.png
-rw-r--r-- 1 abtris 8.0K 2009-09-12 21:14 screenshot-2.png
-rw-r--r-- 1 abtris  16K 2009-09-12 21:14 screenshot-3.png
-rw-r--r-- 1 abtris  18K 2009-09-12 21:14 wp-recentcomments.php

V adresáři languages najde to co potřebujete, je tam hromada souborů s příponou po a mo. To jsou soubory ve formátu pro gettext a mo jsou zkompilované soubory (ty vás nezajímají) a v po souborech najdete zdrojový kód, který je potřeba otevřít pomocí editoru (doporučuji poEdit).

Potom stačí jen přeložit potřebný text, z angličtiny do češtiny a po uložení  se vytvoří soubor (wp-recentcomments-cs_CZ.po) s příponou mo. Pojmenování s koncovkou cs_CZ je potřeba dodržet, aby fungovalo dobře rozpozání jazyka ve WordPressu.

Screenshot-Poedit : -home-abtris-Desktop-wp-recentcomments-languages-wp-recentcomments-cs_CZ.po

Potom si nahrajte upravený plugin na server a máte ho v provozu česky jak vidíte u mne na stránkách.

Dobré je vaši verzi poslat také autorovi ke zveřejnění. Česká verze WP-RecentComments se tam časem až programátor uzná objeví také.

Ukázka přeloženého widgetu dále, pokud máte nějaké připomínky k překladu neváhejte je také uvést v komentářích.

Moje nastavení widgetu pro WP-RecentComments

Nastavení najdete v administraci, Vzhled -> Widgety. Přidáte widget do sidebaru a potom po kliknutí na pravou ikonku rozbalí se vám menu, kterou vidíte na obrázku.

Widgety ‹ Prskavčí blog — WordPress_1252784358148

Categories: wordpress Tags:

Zend_Rest_Route a Zend_Rest_Controller v ZF 1.9

01.09.2009 View Comments

Proč REST a co to obnáší?

V Zend Frameworku 1.9 byla přidána pro používání REST v url a v controlleru.

REST je v módě a proto nám ho přidali i do ZF. Ne vážně samozřejmě každý teď dělá do REST. Implementace RESTu existuje v každém větším frameworku. V ZF už delší dobu je REST klient i server. Klienta můžete využít pro práci s mnohými službami na internetu (twitter, flickr, …).

V tabulce je dobře vidět jak se využije HTTP protokol. Metody PUT, DELETE se běžně nevyužívají.

Akce SQL HTTP
Create Insert PUT
Read Select GET
Update Update POST
Delete Delete DELETE

REST API je součástí mnoha z nich. Pokud máte aplikaci RESTful, není problém potom provozovat i REST api.

  • do ZF byli přidány dvě nové třídy Zend_Rest_Route, Zend_Rest_Controller
  • přinese nám to využití HTTP protokolu (GET, POST, PUT, DELETE)
  • pro používání RESTu změníme controller, budeme používat Zend_Rest_Controller místo Zend_Action_Controller
  • v controlleru je potřeba potřeba definovat tyto metody
    • indexAction()
    • getAction()
    • postAction()
    • putAction()
    • deleteAction()
  • GET je get a všechny destruktivní akce jsou přes POST

Vzal jsem základní tutorial z akrabatu a modifikoval jsem ho pro použití s REST. Zdrojové kódy jsou k dispozici na bitbucketu.

Do bootstrapu je potřeba přidat definici pro Zend_Rest_Route

    function _initRestRoute()
    {
        $this->bootstrap('Request');
        $front = $this->getResource('FrontController');
        $restRoute = new Zend_Rest_Route($front, array(), array(
            'default' => array('albums')
                ));
        $front->getRouter()->addRoute('rest', $restRoute);
    }

    function _initRequest()
    {
        $this->bootstrap('FrontController');
        $front = $this->getResource('FrontController');
        $request = $front->getRequest();
        if (null === $front->getRequest()) {
            $request = new Zend_Controller_Request_Http();
            $front->setRequest($request);
        }
        return $request;
    }

a je potřeba modifikovat controller, aby využíval celký HTTP protokol.

class AlbumsController extends Zend_Rest_Controller
{
    private $_albums;
    private $_form;

    public function init()
    {
        /* Initialize action controller here */
        $this->_albums = new Zend_Db_Table('albums');
     	$this->_form = new Form_Album();
    }

    public function indexAction()
    {
        $this->view->title = "My Albums";
        $this->view->headTitle($this->view->title, 'PREPEND');
        $this->view->albums = $this->_albums->fetchAll();
    }

    public function listAction()
    {
        $this->_forward('index');
    }

    public function getAction()
    {
        $this->view->album = $this->_albums->find($this->_getParam('id'))->current();
    }

    public function putAction()
    {
        $album = $this->_albums->find($this->_getParam('id'))->current();
        if ($this->_form->isValid($this->_request->getParams())) {
            $album->setFromArray($this->_form->getValues())->save();
            $this->_redirect('albums');
        } else {
            $this->view->album = $album;
            $this->view->form = $this->_form;
            $this->render('edit');
        }

    }

    public function postAction()
    {
        if ($this->_form->isValid($this->_request->getParams())) {
	       $this->_albums->createRow($this->_form->getValues())->save();
           $this->_redirect('albums');
        } else {
            $this->view->form = $this->_form;
            $this->view->title = "Add new album";
           $this->render('new');
        }

    }

    public function newAction()
    {
        $this->view->title = "Add new album";
        $this->view->headTitle($this->view->title, 'PREPEND');

        $this->view->form = $this->_form;

    }

    public function editAction()
    {
        $this->view->title = "Edit album";
        $this->view->headTitle($this->view->title, 'PREPEND');
        $album = $this->_albums->find($this->_getParam('edit'))->current();
	    if ($album) {
    	    $this->_form->populate($album->toArray());
	    }
    	$this->view->form = $this->_form;
    	$this->view->album = $album;

    }

    public function deleteAction()
    {
        $this->view->title = "Delete album";
        $this->view->headTitle($this->view->title, 'PREPEND');

    	$album = $this->_albums->find($this->_getParam('id'))->current();
    	$album->delete();
        $this->_redirect('albums');

    }
}
Categories: zend framework Tags: ,

Switch to our mobile site