« Februar 2008 | Main | April 2008 »

März 2008 Archives

05.03.08

Testing Part1: Rails

Bisher habe ich mich davor gedrückt Tests zu schreiben, aber da komme ich nicht länger drumherum.

Das sinnvollste wird wohl sein, alles was ich von Hand teste, mit automatische Tests abzudecken. Customer und Rating anlegen, Fakten eintragen, löschen, usw...

Da ich mich mit Tests noch nicht so auskenne, fange ich dieses Mal mit Rails an, da hier der Einstieg ins Testing einfacher scheint.
Hier erstmal ein paar nützliche Links:
http://manuals.rubyonrails.com/read/book/5
http://nubyonrails.com/articles/ruby-rails-test-rails-cheat-sheet

Nun bringt ein Blick in das Buch "The Railsway" doch Zweifel, ob ich nicht besser das plugin RSpec zum Testen verwenden sollte. So würde ich damit den eigentlichen vorgesehenen Weg von Rails verlassen und das sollte in meinem Vergleich eigentlich nicht passieren. Ich werde mich also mit den mitgelieferten Testmöglichkeiten auseinandersetzen.

Rails hat automatisch schon einige Tests angelegt und da dort zB die später hinzugefügte Validierung noch nicht berücksichtigt wird, bekam ich beim ersten Durchlauf auch jede Menge Fehler.

Die habe ich jetzt repariert, aber es bleiben 2 Tests übrig, die einfach nicht funktionieren wollen. Da brauche ich mal eure Hilfe, denn ich komme einfach nicht weiter...

Also... Hier ein Test, der funktioniert:

def test_should_destroy_rating
assert_difference('Rating.count', -1) do
delete :destroy, :id => ratings(:one).id
end
assert_redirected_to ratings_path
end

Die Fixture dazu:

one:
date: 2008-01-10 02:30:05
rating: 5000
status: COMPLETED
customer: one

Die DB-Tabelle sieht so aus:

create_table :ratings do |t|
t.datetime :date
t.integer :rating
t.string :status
t.references :customer
t.timestamps
end

Alles wunderbar und jetzt der Test, der nicht funktioniert:

def test_should_destroy_fact_type
assert_difference('FactType.count', -1) do
delete :destroy, :id => fact_types(:fact_type_1).id
end
assert_redirected_to fact_types_path
end

Die Fixture dazu (im moment als csv, habe es aber auch schon als yaml gehabt. gleicher fehler:

id,factCategory_id,title,question,question_type
1,2,"Alter des Kunden","Wie alt ist der Kunde?","FREE"

Die DB-Tabelle sieht so aus:

create_table :fact_types do |t|
t.string :title
t.text :question
t.string :question_type
t.references :factCategory
t.timestamps
end

Die Fehlermeldung ist:

MySQL Error: #42S22Unknown column 'facts.fact_type_id' in 'where clause': SELECT * FROM `facts` WHERE (facts.fact_type_id = 1)

Das kann auch nicht funktionieren, weil anstatt "fact_type_id" müsste rails einfach nur die column "id" in der where-clause verwenden. Beim rating klappt das doch auch!? Warum hier nicht? Den einzigen Unterschied den ich sehe ist der Unterstrich im Tabellennamen...
Was übersehe ich?

06.03.08

Testing Part2: Java EE

So. Nun muss ich die Test nur noch für meine Java EE-Anwendung umsetzen. Dafür nimmt man erstmal JUnit und Netbeans hilft dabei. Aber ist das wirklich eine gute Wahl? Immerhin verwende ich JSF und da gibt es andere (bessere?) Möglichkeiten. JSFUnit(beta), JunitEE, Cactus, Selenium, ... und wieder immernoch brauche ich einen JSF-Experten!

Nützliche Links:
http://www.infoq.com/news/2007/12/jsf-testing-tools
http://junit.sourceforge.net/doc/cookbook/cookbook.htm
http://www.junitee.org/

Ein gutes Netbeans-Tutorial für Netbeans habe ich nicht gefunden, aber eigentlich ist das auch nicht nötig. Legt man einen TestCase an (rechtsklick auf die Klasse, für die man den TestCase haben will > Tools > Create JUnit Tests), so kann man zwichen JUnit 3.x oder 4.x wählen, dann noch welche Tests man haben will und die Tests werden im TestPackage erstellt. Also im Prinzip hat man hier - wie bei Rails - Testdummies, die man dann reparieren muss. Das mache ich dann jetzt mal.

Soweit so gut. Allerdings sind diese erstmal nur fürs Backend. Um die WebApp zu testen bräuchte ich HttpUnit oder ähnliches.

UPDATE: Soweit gar nicht gut, weil man nicht einfach EJBs testen kann, da diese ja im AppServer laufen müssen. Man muss also einen Testdienst implementieren, der dann tests in der deployten Anwendung ausführen kann. Oder man nimmt JUnitEE oder Cactus oder...?? Ich finde es erstaunlich wie wenig sinnvolle Hilfe man zu diesem Thema findet. EJBs testen sollte doch eigentlich ziemlich wichtig sein.... Zitat: "Although this [JUnit Testing] works well for most standalone applications, it becomes outrageously complicated when you test code -- like an EJB -- that runs in an application server."

btw: Den Fehler im Rails-Testing habe ich immernoch nicht gelöst. Siehe Blogeintrag von gestern. Bin über Kommentare dankbar.

20.03.08

HOWTO test EJB3 with JUnit outside of the container

Since EJB 3.0, testing should be easy. And it IS much more simpler than with EJB 2.1, because you dont need to have an application server (AS) up and running

Chapter 12 in the book "Pro EJB 3: Java Persistence API" by Mike Keith and Merrick Schincariol was very useful for me.

I'm using Netbeans 6.0, EJB3, JPA and a MySQL-Datebase and i write integration tests. (as defined in the book above: focus on use-cases, decoupled from appserver, making full use of external resources such as database)

First of all i added the library JUnit (4.1) to my Netbeans-Project You can then rightclick on a sourcefile and select > Tools > Create JUnit Tests

Using the Entity Manager
If you're using the Entity Manager (EM) you must create one for your tests. Because no AS is around, you need an EM Factory and for that you need a Persistence Provider. Add the library TopLink Essentials to the project. Without the AS we cant use JTA datasource with JNDI, so i created a mysql testdatabase and added a persistence-unit for testpurposes. To use it i need the MySQL JDBC Driver-library in my project.
My persistence.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="Project-ejbPU" transaction-type="JTA">
    <jta-data-source>jdbc/project_database_jndi_name</jta-data-source>
  </persistence-unit>
  <persistence-unit name="ProjectTest-ejbPU" transaction-type="RESOURCE_LOCAL">
    <class>project.model.entity1</class>
    <class>project.model.entity2</class>
    <class>project.model.entity3</class>
    <class>project.model.entity4</class>
    <class>project.model.entity5</class>
    <properties>
        <property name="toplink.ddl-generation" value="create-tables"/>
        <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/project_test_db_name" />
        <property name="toplink.jdbc.user" value="root"/>
        <property name="toplink.jdbc.password" value="xxx"/>
     </properties>
  </persistence-unit>
</persistence>

Note that the transaction-type should be RESOURCE_LOCAL and not JTA, because we dont want any trouble with JNDI-stuff ;) I've been told that every entity has to be defined explicitly in the persistence.xml

Now you need to create and use the EM in your tests
Change the setUp()-method in the testclass to the following:

    @Before
    public void setUp() {
        yourbean.em = Persistence
.createEntityManagerFactory("ProjectTest-ejbPU")
.createEntityManager(); // your own setUp-stuff }
Now you can write your tests as if your app is deployed in an AS.

About März 2008

This page contains all entries posted to Gerald's Blog in März 2008. They are listed from oldest to newest.

Februar 2008 is the previous archive.

April 2008 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.31