|
Îåêßíçóå áðü ôï ìÝëïò pontifikas. Τελευταία δημοσίευση από το μέλος Πέτρος Αμοιρίδης στις 08-12-2006, 17:08. Υπάρχουν 14 απαντήσεις.
-
25-09-2005, 16:36
|
-
pontifikas
-
-

-
Μέλος από τις 08-06-2005
-
Stuttgart
-
Δημοσιεύσεις 219
-
-
|
Ας πούμε γράφω την εξής loopιά
private int [] foo = new int[4];
private int foobar = 0;
for(int i = 0 ; i <=5 ; ++i)
{
foobar+= foo [ i ];
}
Αυτό το πράγμα όπως βλέπετε θα δημιουργήσει είναι ένα index ot of range
exception. Υπάρχει τρόπος μέσω του VS Να κάνω έλεγχο του Loop (και
γενικά του κώδικα) ώστε να καταλάβω ότι εκεί θα βαρέσει.
Γενικά υπάρχει δυνατότητα προσομοίωσης του προγράμματος και εξάλλειψης
όλων των πιθανών σφαλμάτων πρίν το τρέξω κανονικά?(Μην πεί κανείς "Με
το μάτι" ![Stick out tongue [:P]](/cs/emoticons/emotion-4.gif) )
|
|
-
25-09-2005, 16:43
|
|
Unit testing ίσως; Ψάξε για το NUnit...
Χρήστος Γεωργακόπουλος
|
|
-
25-09-2005, 17:34
|
-
25-09-2005, 17:49
|
|
Έχει ενσωματωμένο και δεν χρειάζεται το NUnit. Υπόψη, το NUnit δεν κάνει μαγικά από μόνο του, χρειαζεται να γράψεις εσύ 2-3 γραμμές κώδικα για κάθε ρουτίνα που θέλεις να ελεγξεις, ώστε να του πεις πως αρχικοποιούνται τα πράγματα και τι παραμέτρους να περάσει στη ρουτίνα. Αυτό είναι μια σχετικά εύκολη αλλά πολύ βαρετή δουλιά, αλλά τα αποτελέσματα είναι καθοριστικά για το development που κάνεις.
Χρήστος Γεωργακόπουλος
|
|
-
25-09-2005, 21:23
|
|
Για validation μπορείς να χρησιμοποιήσεις το FxCop, το οποίο ουσιαστικά είναι ένα static code analyzer. Έχει πολλούς κανόνες και μπορείς να ορίσεις και άλλους δικούς σου.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
04-01-2006, 11:28
|
-
04-01-2006, 12:53
|
|
Frontier wrote: | Άλλος ένας απλός τρόπος είναι με debug builds και με χρήση ASSERT όπου χρειάζεται, ώστε να ξέρεις τι ακριβώς χτύπησε.
Η μέθοδος αυτή είναι πιο "παλιά" από το unit testing, αλλά και πιο απλή στην εφαρμογή της. |
|
Τα asserts δεν είναι παλιότερα ή απλούστερα από το unit testing, αλλά έχουν διαφορετική χρήση. Το unit testing χρησιμοποιείται για να ελέγξει κανείς πως συμπεριφέρεται ένα κομμάτι κώδικα (μια μέθοδος πχ.) όταν καλείται με διαφορετικούς τρόπους (π.χ. μεταβλητές εκτός ορίων, περίεργες αρχικές καταστάσεις). Για να πετύχει κανείς το ίδιο πράγμα με asserts θα πρέπει να γεμίσει τον κώδικα του με πολλά διαφορετικά asserts, τα οποία μπορεί και να μην εκτελεστούν ποτέ. Τα asserts από την άλλη ρίχνουν exceptions όταν ανακαλύψουν ότι απέτυχε ένας έλεγχος, πχ. αν μια τιμή είναι εκτός ορίων. Τα asserts είναι χρήσιμα και στα κανονικά builds, όχι μόνο στα debug builds, καθώς τα πιο περίεργα λάθη εμφανίζονται όταν η εφαρμογή τρέχει κανονικά.
Καμμία από τις δύο λύσεις δεν αρκεί από μόνη της. Τα asserts κάνουν πολύ πιο εύκολο τον εντοπισμό κάποιων λαθών, κυρίως στην τελική έκδοση της εφαρμογής. Μόνο το unit testing όμως ελέγχει ότι μία μέθοδος δουλεύει σωστά με διαφορετικές παραμέτρους.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
04-01-2006, 13:40
|
-
04-01-2006, 17:48
|
|
Τα xUnit frameworks μπορεί να μην υπήρχαν, αλλά το Unit testing υπήρχε από το ... 70 και πριν. Η βασική ιδέα προέρχεται από τα ηλεκτρονικά όπου κάθε εξάρτημα ελέγχεται στέλνοντας κανονικά αλλά και περίεργα σήματα στους ακροδέκτες του και ελέγχοντας τα σήματα στις εξόδους. Αυτή η τεχνική χρησιμοποιήθηκε από την αρχή σχεδόν και στον προγραμματισμό. Αναφέρω το 1970 απλά και μόνο γιατί το πρώτο παράδειγμα που μου έρχεται στο μυαλό είναι μια ιστορία του Fred Brooks (μπορεί να κάνω και λάθος) που περιέγραφε ένα προγραμματιστή compiler για ένα mainframe, ο οποίος έφτιαχνε μικρά τεστάκια για κάθε νέα λειτουργία που δημιουργούσε. Μιλάμε για γλώσσες πριν καν εμφανιστεί η C!
Αν το unit testing αντιστοιχεί στον έλεγχο της απόκρισης ενός εξαρτήματος σε διάφορα σήματα, τα asserts είναι αντίστοιχα με τις ασφάλεις και τα ρελέ. Χρησιμοποιούνται για να "σκάνε" όταν περάσει κάποιο απρόσμενο ή επικίνδυνο σήμα. Και δεν τις αφαιρείς από το τελικό προϊόν.
Όπως οι ασφάλειες δεν αντικαθιστούν τον έλεγχο απόκρισης, έτσι και τα assert δεν αντικαθιστούν το unit testing. Τα asserts θα εξασφαλίσουν ότι ο κώδικας θα "σκάσει" σε κάποιες συγκεκριμμένες συνθήκες, αλλά δεν ελέγχουν τί συμβαίνει σε όλες τις άλλες περιπτώσεις. Αν έχεις μια μέθοδο που υπολογίζει, πχ. δόσεις δανείου, ένα assert θα εμποδίσει την εισαγωγή αρνητικών τιμών αλλά δεν μπορεί να ελέγξει την ορθότητα του αποτελέσματος για θετικές τιμές. Αυτό μόνο με Unit testing μπορεί να γίνει.
Το γεγονός ότι τα unit-testing frameworks έχουν μεθόδους με το όνομα assert ή verify δεν σημαίνει ότι βασίζονται στη λογική των assertions. Τα assertions βρίσκονται μέσα στον κώδικα, όπως οι ασφάλειες μέσα σε μία συσκευή. Μια μέθοδος Test.Assert δεν έχει σχέση με τον κώδικα, απλά συγκρίνει τα πραγματικά με τα επιθυμητά αποτελέσματα και μαρκάρει το κάθε τεστ σαν επιτυχία-αποτυχία. Είναι σαν τον ακροδέκτη ενός παλμογράφου ή ενός πολύμετρου που τον ακουμπάς σε ένα σημείο του κυκλώματος για να δεις αν το σήμα που παίρνεις είναι αυτό που περίμενες.
Τέλος, με το unit-testing βρίσκεις τελείως άλλα και διαφορετικά προβλήματα απ' ότι οι χρήστες. Για την ακρίβεια, όταν κάποιος χρήστης τρέχει την εφαρμογή και ελέγχει τιμές δεν κάνει καν unit-testing. Αυτό που περιγράφεις ονομάζεται feature testing. Ο χρήστης θα βρει τα ποιό συνηθισμένα προβλήματα και κυρίως αυτά που έχουν να κάνουν με τα χαρακτηριστικά που ξέρει καλύτερα. To unit-testing από την άλλη, ελέγχει κάθε μέθοδο και κλάση για να εξασφαλίσει ότι γυρίζει τα αναμενόμενα αποτελέσματα για οποιεσδήποτε παραμέτρους εισόδου. Ο χρήστης δεν μπορεί να τρέξει όλα τα τεστ κάθε φορά που θα του δώσεις ένα πρόγραμμα, ενός τα unit-tests εκτελούνται πάντα, όλα και αυτόματα. Δεν το εκτελεί ένας συγκεκριμμένος άνθρωπος, ούτε βασίζεται σε κάποια λογική.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
05-01-2006, 11:45
|
|
Πσσσσσ....., Παναγιώτη έγραψες.... άψογο παράδειγμα....
Χρήστος Γεωργακόπουλος
|
|
-
05-01-2006, 12:23
|
-
Frontier
-
-
-
Μέλος από τις 21-05-2005
-
Χίος
-
Δημοσιεύσεις 25
-
-
|
Ωραία όλα αυτά, αλλά αφού χρησιμοποιούνται ευρέως (σε μεγάλες εφαρμογές), γιατί πάλι συμβαίνουν run-time exceptions;
Μπορεί να είναι καλό το unit testing, αλλά δεν δέχομαι ότι πιάνει τα πάντα ή ελέγχει τα πάντα, τουλάχιστον αυτό δεν έχει αποδειχθεί ακόμα.
Για τις εφαρμογές μου, φροντίζω να τις "σπάω" σε απλά και μικρά κομμάτια, ώστε να μπορώ να ελέγχω το κάθε ένα εξονυχιστικά. Το unit testing πρακτικά δεν μου έχει δώσει κάποιο όφελος προς το παρόν, μιας που π.χ αν χρησιμοποιείς μια strong-type language (και με overloading) "κόβεις" ό,τι δεν σου αρέσει, αποφεύγοντας το bloat. Εκεί που χρειάζεται περισσότερο το unit testing είναι σε typeless γλώσσες, όπου τα πάντα μπορούν να συμβούν.
Άποψή μου τα παραπάνω, δεν είναι απαραίτητα αποδεκτά απ'όλους.
Best Regards, Manos S. Pappas ClubPocketPC.gr - Mobile Development Admin
|
|
-
05-01-2006, 12:35
|
-
Frontier
-
-
-
Μέλος από τις 21-05-2005
-
Χίος
-
Δημοσιεύσεις 25
-
-
|
Και για να μην παρεξηγηθώ: δεν αμφισβητώ αυτά που λες, αμφισβητώ το ότι το Unit Testing ελέγχει τα πάντα. Η απόδειξη είναι ότι παρ'όλο που χρησιμοποιείται ευρέως (ακόμα και σε ελληνικές εμπορικές εφαρμογές), πάλι συμβαίνουν runtime exceptions που οδηγούν σε τερματισμό της εφαρμογής.
Με τη λογική που αναφέρεις, το unit testing, εφ'όσον έλεγξε τα πάντα (τι πρέπει να δεχθεί μια τάξη, τι να επιστρέψει κ.λπ) σε πραγματικές συνθήκες εκτέλεσης κώδικα, δεν θα έπρεπε να "εντοπίζει" αυτά τα προβλήματα πριν εμφανισθούν; Ξέρω τουλάχιστον δύο περιπτώσεις ελληνικών εφαρμογών ERP που ενώ έχουν υποστεί εκτεταμένο unit-testing, εξακολουθούν να εμφανίζουν απροσδιόριστα σφάλματα κατά την εκτέλεσή τους.
Γιαυτό επιμένω ότι καλό μεν το unit-testing, αλλά επ'ουδενί αντικαθιστά τα debug builds και την χρήση τους από testers σε πραγματικές συνθήκες.
Εκεί που θέλω να καταλήξω είναι ότι καλά μεν όλα αυτά, αλλά αν δεν γράφει ο άλλος σωστό κώδικα... έχασε! Και δυστυχώς οι περισσότεροι προγραμματιστές σήμερα, λόγω της άκρατης χρησιμοποίησης των ευκολιών που τους διατίθενται (βιβλιοθήκες, frameworks κλπ) δεν ξέρουν τι γράφουν, τι χρησιμοποιούν (dependencies), εξ'ου και τα τόσα προβλήματα.
Σταματώ εδώ γιατί νομίζω ότι βγήκαμε αρκετά off-topic :)
Best Regards, Manos S. Pappas ClubPocketPC.gr - Mobile Development Admin
|
|
-
05-01-2006, 12:58
|
|
Όταν γράφεις unit tests, προσπαθείς να φανταστείς όλα τα στραβά που μπορεί να εμφανιστούν και να τα κάνεις handling. Αυτό δεν σημαίνει σε καμία περίπτωση ότι θα τα σκεφτείς όλα. Είναι απλά μια καλή μέθοδος για να πιάσεις τουλάχιστον τις πιο σημαντικές περιπτώσεις, γιατί σε βοηθάει να δεις τα πράγματα από μια άλλη οπτική γωνία από αυτή που γράφεις τον κυρίως κώδικα.
Για όλες τις άλλες περιπτώσεις που δεν μπορείς να σκεφτείς ούτε όταν γράφεις τον κυρίως κώδικα, ούτε όταν γράφεις τα unit test, κάνεις error handling με τέτοιο τρόπο ώστε να ενημερωθείς για το σφάλμα που παρουσιάστηκε στο run-time και να φροντίσεις να το διορθώσεις εκ των υστέρων. Μιά τέτοια μορφή error handling είναι και τα asserts που αναφέρθηκαν.
Όπως λέει και η θεωρία της τεχνολογίας λογισμικού, η απόλυτη τεκμηρίωση του κώδικα είναι θεωρητικά εφικτή, είναι όμως τόσο περίπλοκη που είναι πρακτικά αδύνατο να υλοποιηθεί για την πλειοψηφία των σημερινών εφαρμογών. Γι' αυτό το λόγο δεχόμαστε την παραπάνω διαδικασία και χρησιμοποιούμε unit tests για να πιάσουμε τα "χοντρά-χοντρά" και σωστό error reporting για να πιάσουμε και τα άλλα που ξέρουμε ότι υπάρχουν αλλά δεν μπορούμε να τα σκεφτούμε από πριν.
Χρήστος Γεωργακόπουλος
|
|
-
05-01-2006, 13:16
|
|
Μάλλον έχεις μπλέξει το unit testing με άλλες μορφές testing. Όταν λές ότι σπας τον κώδικα σου σε μικρά κομμάτια που τα ελέγχεις εξονυχιστικά, κάνεις ένα από τα βήματα του unit testing. Από την άλλη, ο έλεγχος σε πραγματικές συνθήκες, ελέγχει άλλα πράγματα, όχι το κάθε μικρό κομμάτι, και κατά κανόνα ελέγχει μόνο τις πιο συνηθισμένες διαδικασίες στην εφαρμογή.
Επιπλέον, αν κάποιος δεν γράψει τα τεστ που ελέγχουν κάποιες λάθος καταστάσεις, πως περιμένεις να τις βρεις? Μπορεί κάποιοι να λένε ότι κάνουν unit testing αλλά στην πραγματικότητα να έχουν γράψει μερικά ελλειπή test scripts κατόπιν εορτής. Αυτό δεν λέγεται unit testing. Ούτε θα σου πιάσει το unit testing προβλήματα συνεργασίας μεταξύ των κομματιών της εφαρμογής. Όπως δεν θα πιάσει το user testing αυτά τα ανεξήγητα runtime exceptions, απλά γιατί σε πραγματική χρήση ο χρήστης θα πάει να κάνει αυτό που δεν είχες ελέγξει στο beta testing.
Εδώ συγκρίνεις ανόμοια πράγματα. Δεν ελέγχει κανείς τη συμπεριφορά μιας βαλβίδας για κινητήρα αυτοκινήτου φτιάχνοντας ολόκληρο το αυτοκίνητο και βγάζοντας το για βόλτα. Ούτε ελέγχονται τα υποσυστήματα ενός επεξεργαστή φτιάχντοντας τον επεξεργαστή από το μηδέν και ελέγχοντας τί κάνει στο τέλος. Αν γινόταν αυτό, η κατασκευή ενός νέου αυτοκινήτου ή ενός επεξεργαστή θα χρειαζόταν δεκαετίες. Από την άλλη, δεν περιμένεις ποτέ ότι αν δουλεύουν όλα τα κομμάτια σύμφωνα με τις προδιαγραφές τους, θα δουλεύει και το αυτοκίνητο ή ο επεξεργαστής σωστά. Φυσικά και θα ελέγξεις ότι τα εξαρτήματα δουλεύουν καλά μεταξύ τους, και φυσικά και θα ελέγξεις και το τελικό αυτοκίνητο ή επεξεργαστή ότι δουλεύει σωστά. Αν όμως περιμένεις να ελέγξεις το αυτοκίνητο για να καταλάβεις ότι η βαλβίδα φθείρεται εύκολα ... ή ότι τα τρανζίστορ που διάλεξες δεν δουλεύουν στις συχνότητες που θέλεις ... είναι πολύ αργά.
Άλλο το unit testing, άλλο το integration testing, άλλο το feature testing, άλλο το user testing. Το καθένα ελέγχει διαφορετικά πράγματα, γίνεται σε διαφορετικές φάσεις της ανάπτυξης μιας εφαρμογής, από διαφορετικά άτομα και ανακαλύπτει διαφορετικά λάθη. Το καθένα από αυτά δεν υποκαθιστά τα άλλα.
Και οι ελληνικές εφαρμογές ERP είναι "διάσημες" για τα προβλήματα τους. Δεν μπορούν να χρησιμοποιηθούν σαν παράδειγμα.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
08-12-2006, 17:08
|
-
Πέτρος Αμοιρίδης
-
-

-
Μέλος από τις 20-09-2006
-
Θεσσαλονίκη
-
Δημοσιεύσεις 69
-
-
|
Αν μου επιτρέπετε να συμβάλλω και εγώ λίγο στη συζήτηση.
Το unit testing είναι ένα εργαλείο στα χέρια μας που μπορούμε να χρησιμοποιήσουμε για να αυτοματοποιήσουμε όσο το δυνατόν καλύτερα τον έλεγχο του κώδικα της εφαρμογής μας. Λέω αυτοματοποιήσουμε, διότι με το πάτημα ενός κουμπιού, μπορούμε να εκτελέσουμε όλα τα unit tests που γράψαμε και δίπλα από το κάθε ένα να ανάψει ένα πράσινο ή ένα κόκκινο λαμπάκι. Το πράσινο σημαίνει ότι πέρασε το τεστ, το κόκκινο σημαίνει ότι δεν πέρασε. Αυτό χρησιμεύει ιδιαίτερα όταν αλλάζουμε κάτι στον κώδικά μας. Με το που τρέχουμε όλα τα unit tests, μπορούμε να δούμε κατευθείαν αν έχουμε "σπάσει" κάποια λειτουργικότητα.
Όσο μεγαλύτερο κομμάτι της εφαρμογής μας καλύπτουμε με unit tests, τόσο καλύτερα ελέγχουμε αυτόματα εάν σπάει ο κώδικάς μας μετά από αλλαγές. Συνεπώς, το unit testing μπορούμε να το χρησιμοποιήσουμε είτε ολοκληρωτικά ή μερικώς. Αυτοί που το χρησιμοποιούν ολοκληρωτικά συνήθως ακολουθούν το λεγόμενο test driven programming.
Το test driven programming λέει ότι πρώτα γράφεις το unit test το οποίο αποτυγχάνει (εφόσον δεν υπάρχει ακόμα ο πραγματικός κώδικας) και μετά προσπαθείς να γράψεις τον κώδικα στην εφαρμογή σου μέχρι το λαμπάκι δίπλα στο τεστ να ανάψει πράσινο (έχει περισσότερες λεπτομέρειες φυσικά το πράγμα, αλλά η βασική ιδέα είναι αυτή). Εγώ μέχρι τώρα δεν κατάφερα να το κάνω αυτό. Αυτό που κάνω συνήθως είναι να χρησιμοποιώ unit tests μόνο σε πολύπλοκο κώδικα ώστε να αποδείξω ότι λειτουργεί με εύκολο τρόπο.
Ένα υπεραπλουστευμένο παράδειγμα test driven programming είναι το παρακάτω:
Έστω ότι θέλουμε να γράψουμε μια method που να παίρνει δύο αριθμούς και να επιστρέφει το άθροισμά τους. Πρώτα γράφουμε το τεστ:
[Test] public void TestAddition() { int result = Add(1,1); Assert.AreEqual(2, result); }
Το παραπάνω δε κάνει compile γιατί δεν έχουμε γράψει την Add. Οπότε την γράφουμε πρώτα:
public int Add(int firstNumber, int secondNumber) { return 0; }
Αν τρέξουμε πρώτα το Τεστ, θα δούμε ότι είναι κόκκινο. Αν συμπληρώσουμε τώρα το σωστό κώδικα στην Add:
public int Add(int firstNumber, int secondNumber) { return firstNumber + secondNumber; }
Τώρα το τεστ γίνεται πράσινο.
Ωχ... πολλά έγραψα... σόρρυ παιδιά. :-)
Πέτρος
Πέτρος
|
|
|
|
|