2008-02-12

Mobilhelyzet, Android

Lassan közeledik az Android Developer's Challenge névleges határideje, most van Barcelonában a Mobile World Congress (cikk róla magyarul) amin biztos bemutatnak pár Androidos prototípust, ráadásul januárban volt egy Sun Mobile Embedded Developers Days is (ahol inkább nyilván a JavaME-t és a JavaFX-et hájpolták, de elhangzott egy olyasmi mondat, hogy az "Android mindenesetre kiváló bizonyíték rá, hogy a mobil technológiában lenne mit jobban csinálni"), úgyhogy íme néhány link az Androidról és a mobil technológiáról, ami összegyűlt az utóbbi időben.

Megjelent egy könyv "Nehogy már a mobilod nyomkodjon téged!" címmel. Tartalomjegyzéke megtekinthető itt. Van szó benne Androidról is (kb 10 oldal), de alapvetően MIDP-re és Netbeansre épít.

Itt pedig egy szerintem kifejezetten ronda, ráadásul valószínűleg kamu Android kütyü látható élőben. A kanadai La Mobile egy HTC Qtek 9090-esbe tett Andriodot. Ugyanerről a Webisztánon.

Cikk a Webisztánon arról, hogy elkésett-e az Openmoko. Ugyanitt videó a Bp Meetup-os Android előadásról. A meetup-on előadó Kis Gergely elérte, hogy egy Zaurus SL-C760-on fusson a Google Android (ezt is a Webisztános Openmoko cikk kommentek között találtam.)

Developer Podcast, amit meg akartam nézni de elnapolódott, úgyhogy nem tudom mi van benne.

Javafórumról link egy blogra, ami azt fejtegeti, hogy megéri-e nevezni az ADC-re, valamint egy másik, hogy kinek hoz pénzt. A Részvételi feltételek hivatalos oldala. Egyébként a március 1-es határidőt meghosszabbítják április 14-ig. Jó ötlet, bár nem érint.

Sok Android hír mp3-ban még decemberből. Nem muszáj meghallgatni, a fontosabb linkek kinn vannak az oldalon. Ha már JavaPosse, itt van egy interjú a JavaME-ről.

NetBeans plugin Roumen-nél, hogy ne csak az Eclipse-esek örüljenek.

Futtassunk Scala-t az Androidon!

Az Androidra visszakanyarodva, decemberben elméletben még foglalkoztatott az ADC-n való indulás, de aztán más melók miatt elkallódott ez a törekvés. Szerintem olyanoknak volt érdemes ezzel foglalkozni, akik egyébként is mobil (MIDP) alkalmazásokat csinálnak és viszonylag kevés plusz munkával át tudják portolni Androidra a cuccot. Ezzel viszont az a gáz, hogy a G-nek át kell adni a szoftvert, legalábbis a kliens oldalt. Ahogy a fenti linkek valamelyike említi nem túl jó biznisz anyagilag az ADC, legfeljebb hírnév szempontjából.

Egy olyan alkalmazáson gondolkodtam, ami a mobil kameráját (majdnem mindben van már) vonalkód leolvasására használja. Sima kereskedelmi vonalkódokat és speciális vonalkódokat tudna leolvasni, amik pl. URL-eket tartalmaznának.

A kockázatelemzésig nem jutottam el, szóval nem tudom, hogy egy mobilos kamera egyáltalán be tudna-e fókuszálni rendesen egy szokásos méretű kereskedelmi vonalkódot. Lehet hogy nem. Az URL-es vonalkód viszont spanyolviasznak bizonyult, mert már létezik ilyen és Semacode néven fut, csak sehol sem használják. Legalábbis sehol sem láttam még.

Pedig jó buli lenne rányomni plakátokra, hirdetésekre, menetrendekre, buszmegállókra, bögrékre, pólókra, kocsira, sportolókra, járdára, házfalra a szokásos nyomtatós, matricázós technológiával (micsoda kampánylehetőségek!), aztán lehetne böngészni, letölteni, vásárolni, rendelni, belenézni, utánanézni, belehallgatni, játszani, tippelni, fogadni az URL bepötyögése nélkül.

A szokásos vonalkódokat leolvasva pedig árösszehasonlító, vélemény megmondó, statisztikai oldalakon lehetne lekérni az adott termékről az információkat, nem azt amit helyben a boltban hazudnak róla.

Na, ti örülnétek ilyen alkalmazásoknak?

Update 2008.12.09: Közben ahogy a megjegyzésekben is írtam, az ADC-n is igen jó helyezést ért el egy ilyen vonalkódolvasó szoftver, és a sima mobilgyártók is kezdik felnyitni a szemüket.
Update 2009.01.23: Ismét egy sg.hu cikk. Ahogy látom Japánban már több éve használják a 2D vonalkódot. Olyan is van, hogy Semapedia.

2008-02-04

JUnit 3.8 Intermed

Azt gondolná az ember hogy tesztesetek írása csupa unalmas ujjgyakorlat.
Itt most ismét JUnit 3.8-as dolgokról lesz szó + általános elvekről.

Failures vs Errors


Alapvetés: A failure és az error is elbuktatja a tesztesetet. A failure-re számítunk, az error-ra nem.

A failure AssertionFailedError-t eredményez. Hogyha a teszt amiatt bukik el, hogy a setUp()-ban vagy a tearDown()-ben exception keletkezett, az pl. error-t eredményez.

Figyelem: A fail()-t és az elbukott assert-eket elkapja a catch(Error), mivel ezek AssertionFailedError-t dobnak. Úgyhogy ha valami (különös) oknál fogva Error-t kell elkapnunk vagy ellenőriznünk, az AssertionFailedError-t tovább kell dobnunk, mert különben szépen csendben elnyelődik. (Pl. külön catch ágat adhatunk az AssertionFailedError-nak.)

A teszt metódusokat el lehet látni throws kitétellel. Ha bekövetkezik az exception, Failure lesz a teszt eredménye. Az a mondás, hogy jobb throws kitételt írni a teszt metódushoz, mint a metóduson belül catch-sel elkapni és kézzel fail-t hívni. "Sosem kapjunk el nem várt exception-öket."

Text test runner kimenetei:
. pass, F:failure, E:error

Assertions


Az asserteknél általában mindig az első paraméter a várt, a második a kapott érték. Ha message is tartozik az assert-hez, az ezeket mind megelőzi.

assertNotNull: van ilyen, nem kell assertEquals(true, obj==null)-t használni.

Az assertSame szolgál a referenciaegyenlőség vizsgálatára.

Az assertEquals nem használható tömbök egyezőségének vizsgálatára. Tömbök egyezőségének vizsgálatához ez ajánlott:
assertTrue(java.util.Arrays.equals(expected, actual));

Redundant assertion antipattern: pl. assertTrue(true)-t betenni olyan helyekre (több helyre), ahova szerintünk elér a vezérlés.

Egyebek


junit.extensions package: A test decorator-ok, mint például a RepeatedTest arra valók, hogy különféle kiegészítő viselkedéseket vezessünk be a tesztek futása előtt illetve után. A test decoratorok tehát nem test suite-ok.

Nem lehet párhuzamosan (szimultán) teszt metódusokat futtatni egy TestCase-en belül. Az ActiveTestSuite-tal lehetőség van tesztek futtatására oly módon, hogy minden hozzáadott TestCase külön szálban indul el párhuzamosan, de a TestCase-eken belül a teszt metódusok továbbra is egymás után hajtódnak végre valamilyen sorrendben.

Interfészekkel tesztelni egyszerűbb. Emiatt (extrém megközelítés) a tesztelés szempontjából elónyösebb, ha a tesztelendő komponensben minden interfész. (A lokális változók, a visszatérési értékek és a függvény paraméterek.)

Hogyan győződhetünk meg róla, hogy a tesztjeink függetlenek egymástól:
-Ugyanazokat a teszteket futtassuk kétszer egymás után.
-Futtassuk a teszteket különböző sorrendben.
-Néhány tesztet üssünk ki mesterségesen és győződjünk meg róla, hogy a többi teszt továbbra is rendben lefut.

A TestSetup osztállyal lehetőség van a normál setUp és tearDown működést kiegészíteni pl. így:


public class TestBigClass extends TestCase {
public void testMethod1() {
System.out.print("A");
}

public void testMethod2() {
System.out.print("B");
}

public static void customSetUp() {
System.out.print("C");
}

public static void customTearDown() {
System.out.print("D");
}

public void setUp() {
System.out.print("E");
}

public void tearDown() {
System.out.print("F");
}

public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(TestBigClass.class);

TestSetup setup = new TestSetup(suite) {
public void setUp() {
customSetUp();
}

public void tearDown() {
customTearDown();
}
};
return setup;
}
}


A futtatás eredménye: CEAFEBFD vagy CEBFEAFD, mivel A és B sorrendje elvileg véletlenszerű, tehát a custom setup és teardown közrefogja a teszteket a normál setup és teardown-okkal együtt.

A JUnit a lelke mélyén nagyjából a következő template metódust használja a tesztek futtatásához:

public void runBare() throws Throwable {
setUp();
try {
runTest();
} finally {
tearDown();
}
}

Fontos megállapítás, hogy mindent dobhat (throws Throwable) és a tearDown() mindenképpen lefut.

Minták


Mock object: stub (static return)- fake (not yet implemented) - mock (valamit csinál) Bővebben.
Self-shunt: A tesztosztály egy callback jellegű interfészt implementál, ahol magukba a callback metódusokba írjuk az assert-eket.
Crash test dummy: Hibakezelés tesztelésére. Szándékosan hibát idézünk elő. Elkapjuk a várt kivételt és esetleg megvizsgáljuk a paramétereit vagy a környező változókat.
AbstractTestCase: Az absztrakt teszt eseteket is a TestCase osztályból örököltetjük, csak teszünk bele absztrakt metódusokat, például különféle factory metódusokat amelyek a tesztekhez szükséges objektumokat gyártják le. Az absztrakt tesztosztályban csak a közös vonásokat teszteljük le.
Extract repetitive setup code to fixture: Ne ismételjünk fölöslegesen a teszt metódusokon belül. Emeljük ki az ismétlődő dolgokat a fixture-ökbe: setUp(), tearDown().
Collecting Parameter Pattern: Amikor több tesztmetóduson keresztül kell összegyűjteni az eredményeket, akkor a metódusnak átadhatunk egy paramétert, amibe az eredményt belepakolhatja. A junit.framework.TestResult egy olyan osztály, amit erre felhasználhatunk. Tárolja hogy mennyi teszt futott összesen, tárolja az error-ral és failure-rel elbukott tesztek referenciáit.
Parameterized test case: Egy előző postban már írtam ilyesmiről, JUnit4 témában. Nem tudom 3.8-ban hogyan működik.
Base test case: Erről nem találtam semmit, de biztos köze van az öröklődéshez.
Good test naming: Nevezd el ésszel a teszteseteidet.

Linkek