daniel

 

“Unit Tests? Pff, brauch’ ich nicht.” – “Was ist das?” – “Viiiiel zu aufwändig.”

So oder so ähnlich sind die Reaktionen auf die beiden kleinen, unscheinbaren Wörter, die vor allem nach einem klingen: Eine Menge Arbeit.

Dabei sind Unit-Tests eigentlich gar nicht so kompliziert und definitiv nützlich. Ich möchte euch eine kleine Einführung ins Thema geben, und euch ermutigen, ihnen zumindest eine Chance zu geben.

Am Anfang war die Klasse… oder?

Unit Tests (Modultests im Deutschen) sind schon länger ein Begriff, werden aber dennoch immer noch zu selten eingesetzt, auch wenn hier einige Open Source – Projekte eine Vorreiterrolle einnehmen. Grundsätzlich geht es bei Unit Tests darum, die Funktionen einer Klasse zu testen, und zu prüfen, ob die Ausgabe mit den erwarteten Ergebnissen übereinstimmt.

Ein kleines Beispiel:

using System;

public class TestKlasse
{
    public int Multipliziere(int a, int b)
    {
        return a * b;
    }
}

Zugegeben, das Beispiel ist trivial. Aber zur Demonstration soll es erstmal genügen. Diese Klasse stellt eine Methode zur Verfügung, mit der ich zwei Werte multiplizieren kann.

Um nun die Ausgaben zu testen, erstelle ich einen Black-Box-Test, d.h., ich vergleiche die Ausgabe der Funktion mit meinen erwarteten Werten. Hierbei hilft mir eine Modultest-Software. Ich habe zwei Möglichkeiten:

  • Ich nutze entweder den internen Unit test des Visual Studios, oder…
  • …ich verwende NUnit.

Für dieses Beispiel entscheide ich mich für NUnit. Die Verwendung ist eigentlich recht simpel: Zuerst lädt man sich die NUnit-Installationsdatei herunter und installiert NUnit. Anschließend fügt man dem Projekt eine Klassenbibliothek hinzu. Am Besten erstellt man pro Klasse im Programm eine Klasse zum Testen. Hier in diesem Falle also eine Testklasse für unsere – äh – TestKlasse

using System;
using NUnit.Framework;

[TestFixture]
public class TestKlasseTest
{
    [Test]
    public void MultipliziereTest()
    {
        int a = 5;
        int b = 6;

        TestKlasse TK = new TestKlasse();

        //Grob überschlagen: 5 * 6 = 30
        Assert.AreEqual(30, TK.Multipliziere(a, b));
    }
}

Ok, was ist hier passiert? Nun, zuerst wird dem neuen Projekt die Assembly NUnit.Framework hinzugefügt. Anschließend bekommt die Klasse das Attribut TestFixture, und jede einzelne Testmethode das Attribut Test. Eine Methode im Unit Test hat grundsätzlich den Rückgabewert void und keinen Parameter.

Anschließend wird die Assembly kompilliert. Jetzt kommt wieder NUnit ins Spiel. Bei der Installation wurde eine GUI installiert, über die ihr die Assembly laden könnt. Über “Run” könnt ihr nun den Test ausführen. Ist der Test erfolgreich, solltet ihr nur noch grün sehen…

Alles grün - alles gut. :)

Alles grün - alles gut. :)

Sollte doch noch ein Fehler auftreten, so könnt ihr den Fehler im Quellcode korrigieren und anschließend neu kompillieren. Anschließend könnt ihr einfach erneut auf Run klicken.

Warum Unit tests?

“Ok”, mögt ihr jetzt sagen, “ich soll also extra Arbeit investieren, um ein paar Funktionen zu testen. Und wer zahlt mir das?” Berechtigte Frage. Direkt natürlich keiner, indirekt der Kunde. Folgende Überlegung:

Ich schreibe für den Kunden ein Modul, und benutze keine Unit tests. Das Modul weist Fehler auf, ich muss nachbessern. Der Kunde wünscht nach einiger Zeit eine Erweiterung, ich setzte sie um, und es schleicht sich wieder ein Fehler ein. Ich muss wieder nachbessern. Mein Problem: In der Zeit, wo ich Nachbesserungen vornehmen muss, kann ich keine anderen Aufträge bearbeiten. Schlimmer noch: Eventuell handelt es sich um aufwändigere Nachbesserungen und der Kunde erleidet Verdienstausfälle, die er mir womöglich noch in Rechnung stellen kann.

Habe ich stattdessen Unit tests benutzt, kann ich nach dem Ändern (und ggf. Anpassen des Tests) den Test laufen lassen und sehe sofort, wenn sich etwas nicht wie geplant verhält. Ich habe weniger Verdienstausfälle und der Kunde ist glücklich. So amortisiert sich die zusätzliche Zeit, die man für die Tests investieren muss, recht bald.

Weitere Hinweise…

An dieser Stelle sei auf die offizielle NUnit – Dokumentation verwiesen. Natürlich gibt es an dieser Stelle noch mehr Möglichkeiten: Exceptions, komplexere Klassen, Test-Suiten etc…

Auch sollte man sich einmal mit Testgetriebener Entwicklung beschäftigen, ein sehr interessantes Thema.

 

Mittlerweile warte ich seit einem Vierteljahr auf die Freischaltung meiner VDSL-Leitung. Vorgestern habe ich mal wieder bei der Hotline angerufen. Man versprach mir den Rückruf eines Technikers, besagter Rückruf ist jedoch nie erfolgt. Auch im Forum bekommt man momentan keine Antwort.

Wie auch immer dieser Fall endet: Nach Ablauf der zwei Jahre sieht mich die Telekom nicht wieder!

 

So kann man recht einfach 2 oder mehrere Dictionaries zusammenfügen. Behandelt allerdings keine Kollisionen!

public static class DictionaryExtensions
{
    // Works in C#3/VS2080:
    // Returns a new dictionary of this ... others merged leftward.
    // Keeps the type of 'this', which must be default-instantiable.
    // Example:
    //   result = map.MergeLeft(other1, other2, ...)
    public static T MergeLeft<T,K,V>(this T me, params IDictionary<K,V>[] others)
        where T : IDictionary<K,V>, new()
    {
        T newMap = new T();
        foreach (IDictionary<K,V> src in
            (new List<IDictionary<K,V>> { me }).Concat(others)) {
            // ^-- echk. Not quite there type-system.
            foreach (KeyValuePair<K,V> p in src) {
                newMap[p.Key] = p.Value;
            }
        }
        return newMap;
    }

}

Besten Dank an pst

 

Tja, wie es scheint, habe ich wieder Recht gehabt. Telekom…

Mittlerweile sind fast 4 Wochen vergangen, ich habe immernoch keinen VDSL-Anschluss. Also heute mal die Hotline bemüht. Nach 15 Minuten Warteschleife bekam ich dann eine Mitarbeiterin an den Hörer. Ihre Antwort, auf meine Frage, wie der Status meiner Call & Surf Comfort VDSL 25 – Schaltung ist:

“Momentan sind leider keine Ports frei.”

Es ist wohl in Bearbeitung, man rechnet mit Oktober. Einen verbindlichen Termin konnte sie mir natürlich nicht nennen. Ich denke, ich rufe in einer Woche nochmal an.

 

Wtf? “Schick ihr eine Nachricht”?!

Hallo Schatz, ich schicke dir dieses Jahr lieber eine Nachricht über Facebook. Alles Gute zu unserem Jahrestag. Machst du nachher Essen und bringst noch Tomaten mit?

Waaaaaaaaaaaaaaaaaah………

 

Jaja, das böse Google AdWords…

Heute ist es gulli.com zum Verhängnis geworden. Unten rechts wird doch recht prominent ein Werbeverweis auf ein christliches Aktionsbündnis gegeben:

Ich möchte das Bündnis nicht verlinken, zitiere aber an dieser Stelle gerne mal die Eckpunkte:

Konkret sollte die Union folgende politische Projekte beschließen:

  • Deutschland braucht einen Aktionsplan für den Jugendmedienschutz, um der zunehmende Erotisierung und Pornographisierung der Jugend sowie der Gesellschaft Herr zu werden.
  • Die Union muß entschlossen ein Adoptionsrecht für homosexuelle Paare verhindern und gegen die familienfeindlichen Projekte aus der Rotgrünen Koalition wie die sog „Homo-Ehe“ vorgehen.
  • Deutschland braucht einen Aktionsplan für das Lebensrecht der Ungeborenen. Die CDU muß sich klar und deutlich dazu bekennen, das Verbot der Abtreibung in Deutschland und die konsequente Durchsetzung des Rechts auf Leben ALLER Menschen anzustreben.

Jawoll – zurück ins Mittelalter. Niedlich ist auch die Forderung, die BRAVO zu verbieten (pff, meinetwegen, mochte sie eh noch nie) und die Aufklärung von Kindern in der Grundschule über Homo- und Bisexualität zu unterbinden. Jetzt fehlt eigentlich nur noch die Forderung, dass jeder Bürger ein 50 vom Hundert seines Lohnes an die Kirche abtreten muss und ein Besuch der Kirche jeden Sonntag als bürgerliche Pflicht festgelegt ist.

Sorry, aber die ganze Aktion “Kinder in Not” zu nennen, ist reinste Blasphemie. Unsere Kinder sind in Not, ja. Aber nicht, weil Sie in der Schule etwas über Bisexualität lernen. Nicht, weil sie von homosexuellen Paaren adoptiert werden. Sondern weil ihre (im übrigen meist heterosexuellen) Eltern nicht genug Kohle haben, um ihren Kindern was zu fressen zu kaufen. Weil Erziehung, ganz nach dem Vorbild aus der Wirtschaft, “outgesourced” wird. Weil es ja doch irgendwie einfacher ist, wenn sich andere darum kümmern. Das ab 2013 ein Krippenplatz für Kinder unter 3 Jahren garantiert ist, macht die Sache dann auch noch viel einfacher. Von Geburt an können sich andere um die Kinder kümmern.

An sich ist  das gar nicht verwerflich. Viele Paare vertrauen ihre Kinder einer Tagesmutter (neudeutsch “Nanny”) an, um Kohle ranzuschaffen, meist sogar recht viel. Aber in den letzten Jahren ist der Anteil der Eltern, die ihre Zeit statt mit Kindererziehung lieber mit “Gäms” und “soschäl nätwörkink”, gefühlt gestiegen. Ach, nicht zu vergessen das Nachmittagsprogramm, was einem ja vorführt, wie das “echte” Leben aussieht.

Dummerweise helfen uns fundamentalistische Ansichten bei diesen Problemen nicht wirklich. Ich denke, gulli würde sich einen Gefallen tun, wenn es diese Werbung unterbinden würde. Es passt irgendwie so gar nicht.

 

Ich muss gestehen, ich bin gerade ein bisschen baff. Ich hatte vor einiger Zeit mal einen Audioplayer geschrieben, SmallTune.

Die Entwicklung habe ich irgendwann Ende 2010 zu Gunsten eines anderen Projektes eingestellt. Heute habe ich mir dann mal die Statistiken meiner Webseite angesehen, und dabei sind mir die Links vom com! – Magazin aufgefallen.

Nach etwas Recherche war dann klar – SmallTune wurde im Mai 2010 das erste mal vorgestellt. Damit ist SmallTune mein erstes Programm, was jemals in einer Zeitschrift erwähnt und auf CD/DVD gepresst wurde!

YEAAAAH!!!

 

Es ist mal wieder einer Hackergruppe gelungen, den Shop von K&M Elektronik zu hacken. In dem Thread finden sich auch drei Mirror mit den Datenbankschemata. Eine Tabelle ist mir dabei besonders ins Auge gefallen:

+++++Table: Artikel

+++Columns:

ArtNr

Gruppe

Untergruppe

Name

Hersteller

HerstArtNr

Beschreibung

Infos

Zubehoer

winner

Preis

PreisF

HPreis

HPreisF

KPreis

GPreis

KoPreis

PromoPreis

PromoPreisF

KoSyEk

BPreis

EkPreis

usb1

usb1_anz

usb2

usb2_anz

ps2

ps2_anz

parallel

seriell

seriell_anz

s-ata_anz

pci_mb

pci_mb_anz

agp

agp_art

ide_anz

fdd

raid_mb

raid_mb_anz

lan_mb

lan_mb_anz

lan_mb_art

chipsatz_mb_art

firewire_mb

firewire_mb_anz

formfaktor_mb

fsb_mb

pciex1_mb

pciex1_mb_anz

pciex16_mb

pciex16_mb_anz

sound_mb

sound_mb_art

maxram_mb

sound_mb_anschluesse_art

spe_art

spe_anz

spe_size

spe_latenz

spe_typ

protokoll_art

laufwerk_ausrichtung

cache

buffer_underrun

einschub_art

verpackung

zugriffszeit

speed_read_cd

speed_read_dvd

speed_write_cd

speed_write_cdrw

controller_ans

cpu_cool_for_art

cpu_cool_db

cpu_cool_volume

cooler_umdrehungen

cpu_cool_befestigung

cpu_cool_material

cpu_cool_ans

cpu_sockel_art

codename

cpu_takt

herstellungsprozess

abmessung_b

abmessung_l

abmessung_h

aufloesung_farbe

ausfloesung_sw

drucker_art

speed_print_farbe

speed_print_sw

papierformat

tasten_anz

hdd_umdrehungen

hdd_formfaktor

hdd_kapazitaet

anschluss_allg

geh_groesse

geh_formfaktor

nez_watt

einschub_extern_525

einschub_intern_35

einschub_extern_35

graka_chipsatz

graka_steckplatz

graka_kuehlung

graka_ramdac

graka_spe_size

tv_in

tv_out

vivo

max_res

farbtiefe

responsetime

mon_groesse

mon_ans

gewicht

mon_kontrast

mon_helligkiet

mon_panel

mon_tco

mon_freq_h

mon_freq_v

lautsprecher_art

lautsprecher_integriert

fernbedienung

tv_ans

cinch_ans

composite_ans

mpeg_decoder

mpeg_decoder_art

svhs

tuner_art

teletext

unterstuetzte_os

radio_tuner

gameport

port_anz

firewall_art

vpn_support

nb_akku_laufzeit

nb_laufwerk_art

nb_graka

modem

modem_art

medium_format

sof_art

kanalbuendelung

voip_faehig

pcix64

pcix64_anz

s-ata

sondertasten_anz

controller_raid_sata

controller_raid_sata_anz

controller_raid_sata2

controller_raid_sata2_anz

controller_raid_scsi

controller_raid_scsi_anz

speed_read_dvdram

speed_write_dvdram

einbau_art

mon_netzteil

externe_hdd_stromzufuhr

graka_core_takt

graka_Speicher_takt

sli_support

dualchannel_support

layout_tastatur

nez_geh_vorh

geh_80mm

geh_92mm

geh_120mm

geh_60mm

geh_80mm_anz

geh_92mm_anz

geh_120mm_anz

geh_60mm_anz

nez_pciex16_ans

nez_525_ans

nez_sata_ans

nez_tc

nez_ans_atx

nez_35_ans

nez_luefter_manreg

nez_amp_33

nez_amp_5

nez_amp_12v1

nez_amp_12v2

nez_ans_atx2

nez_ans_eatx

nez_luefter_anz

nez_luefter_groesse

graka_dx_version

nez_ans_atx12v

nez_pfc_art

bkanal_anz

nez_sata

nez_amp_12v

graka_ans

geh_frontans

geh_frontans_art

speed_write_dvdplus

speed_write_dvdminus

speed_write_dvdplusrw

speed_write_dvdminusrw

speed_write_dvddl

dvd_dl_support

spe_mb_anz

cpu_cache_l2

mau_art

mau_tasten

tast_typ

mau_typ

cpu_bit

cpu_typ

sca_scan_size

sca_max_res

sca_farbtiefe_sw

nez_luefter_vorh

cpu_cool_luefter_size

kab_laenge

kab_art

kab_typ

prod_farbe

streamer_art

streamer_size

bea_ansi_lumen

MTBF

bea_lampe_watt

mpeg_decoder_typ

time_shift

mic_vorh

lan_standard

mod_integriert

uplink_vorhanden

firewall_vorhanden

nb_mb_chipsatz

dig_spe_art

graka_onboard

fdd_vorh

kosy_cpu

rohling_speed

roh_anz

rohling_art

rohling_size

pat_fuellmenge

pat_seiten

raid_vorh

raid_0

raid_1

raid_01

raid_10

raid_5

raid_jbod

cam_dig_zoom

cam_opt_zoom

cam_mega_pixel

cam_spe_medien

card_reader_vorh

Einbaugrosse

einbaugroesse

lueftersteuerung_vorh

material

externe_hdd_art

force_feedback_vorh

pda_gps

pda_int_spe

graka_spe_interface

spe_bestueckung

cpu_mmx

cpu_3dnow

cpu_sse

cpu_sse2

cpu_sse3

dvd_ram_support

nez_pciex16_vorh

spe_ecc

pciex4_mb

pciex4_mb_anz

geh_120mm_anz_erw

geh_60mm_anz_erw

geh_80mm_anz_erw

geh_92mm_anz_erw

speed_write_dvddlminus

dvd_dl_support_minus

crossfire

ide_vorh

nez_ans_atx12v2

cpu_cores

nez_amp_12v3

nez_amp_12v4

cpu_sse4

speed_read_bdr

speed_write_bdr

speed_write_bdre

speed_read_hddvd

BlueTooth

os

webcam

han_umts

han_cam

han_art

han_touch

han_epush

nez_amp_12v5

nez_amp_12v6

kosy_art

nez_pciex16_ans_8

kosy_graka

dvd_lightscribe

nez_mod

kab1_ans

kab2_ans

eSATA

art_sof

art_zub

cpu_sse4a

cpu_sse41

cpu_ssse3

controller_sas

cam_art

trichannel_support

Ihr habt das Ende erreicht. :) In der kompletten Tabelle  befinden sich also Felder zur Beschreibung für jedes erdenkliche Produkt. Ich weiß nicht, wie ihr das seht, aber das UPDATE – und INSERT – Statement dafür sieht bestimmt lustig aus. :)

Man hätte hier die Datenbank zumindest in Ansätzen normalisieren können. Beispielsweise so:

+++++Table: Artikel
+++Columns:
ArtNr
Gruppe
Untergruppe
Name
Hersteller
HerstArtNr
Beschreibung
Infos
Zubehoer
winner
Preis
PreisF
HPreis
HPreisF
KPreis
GPreis
KoPreis
PromoPreis
PromoPreisF
KoSyEk
BPreis
EkPreis

+++++Table: Zusatzdaten_PC
++Columns
***Spalten, die man für einen Komplett-PC benötigt***

+++++Table: Zusatzdaten_Notebook
++Columns
***Spalten, die man für ein Notebook benötigt***

+++++Table: Zusatzdaten_Digitalkamera
++Columns
***Spalten, die man für eine Digicam benötigt***

 

+++++Table: Zusatzdaten_Zuordnung
++Columns
ArtikelID
Zusatzdaten_PC
Zusatzdaten_Notebook
Zusatzdaten_Digitalkamera

So in etwa. Die Zuordnungstabelle könnte man auch noch erweitern und bspw allgemeiner fassen. Jedenfalls dürfte das übersichtlicher sein, als alles in eine Tabelle zu rotzen. Auf der anderen Seite erklärt das aber auch, weshalb die Seite gehackt werden konnte. Ich vermute einfach Stümper am Werk.

 

Ich habe mal wieder etwas mit Blender gearbeitet. Herausgekommen ist dabei, basierend auf einem Tutorial des Blender-Gurus ein Spiegelbild, wie ich sie auch gerne fotografiere. Die Spiegelung ist ein Foto, welches ich geschossen habe, bei dem Pflaster handelt es sich um eine Textur, zusammen mit einigen Effekten. Es erinnert mich auf jeden Fall an unseren gemeinsamen Berlin-Urlaub. Das Bild gibt es als Wallpaper im Anhang. ;)

 

Zum Speichern auf "Ziel speichern unter..." o.ä. klicken (1280x800)

 

Es ist nun zwei Wochen her, das die Telekom meinen neuen Anschluss geschaltet hat. Allerdings ist noch immer keine Spur von VDSL vorhanden. Ich denke, es ist langsam an der Zeit, dem Kundencenter etwas auf die Füße zu treten.

© 2012 danielgilbert.de Suffusion theme by Sayontan Sinha