Jak szybko przetestować taki kod?

0

Hej

Napisałem kawałek kodu, sprawdza czy data jest prawidłowa. Zastanawiam się jak szybko mogę przetestować różne przypadki czy to działa tak jak należy?

#! python3
# Date Detection - Checks if date is correct.
import re

# Regular expression for date in format: DD/MM/YYYY
date_regex = re.compile(r'([0|123]\d)/(\d{2})/(\d{4})')

# Input validator (main loop)
while True:

    print('Enter date in format DD/MM/YYYY: ')
    date_input = input()

    date_entered = date_regex.search(date_input)

    if date_entered is not None:

        month = date_entered.group(2)
        months = ['01', '02', '03',
                  '04', '05', '06',
                  '07', '08', '09',
                  '10', '11', '12']

        year = int(date_entered.group(3))
        if year > 3000 or year < 1000:
            print(f'Error. Enter year in range: 1000-2999 ({year})')
            continue

        if month not in months:
            print(f'Error. Enter month in format MM (range 01-12) ({month})')
            continue

        # TODO: Shorten the code
        day = int(date_entered.group(1))
        wrong_day = 'Wrong day.'
        if month == '01':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '02':
            if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
                if day not in range(30):
                    print(wrong_day)
                    continue
            else:
                if day not in range(29):
                    print(wrong_day)
                    continue
        elif month == '03':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '04':
            if day not in range(31):
                print(wrong_day)
                continue
        elif month == '05':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '06':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '07':
            if day not in range(31):
                print(wrong_day)
                continue
        elif month == '08':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '09':
            if day not in range(31):
                print(wrong_day)
                continue
        elif month == '10':
            if day not in range(32):
                print(wrong_day)
                continue
        elif month == '11':
            if day not in range(31):
                print(wrong_day)
                continue
        elif month == '12':
            if day not in range(32):
                print(wrong_day)
                continue

        print('Date is valid.')
        break

    else:
        print('Error. Wrong format.')
        continue
0

Wyodrębnić logikę do funkcji, przyjmować string z datą, zwracać wynik walidacji, testować tą funkcję.

0

Jak wyżej, w Pythonie jest też gotowy obiekt do dat:
https://docs.python.org/3/library/datetime.html

0

Okej, poprawię to dzisiaj. Myślałem, że są jakieś szybsze metody testowania takich rzeczy.

2

Myślałem, że są jakieś szybsze metody testowania takich rzeczy.

Bo są, jak napiszesz kod jak człowiek :) Teraz to nijak nie da się tego testować bo wszystko leci w pętli w main i opiera się na printowaniu błędów. Jakbyś miał osobną funkcje która zwraca jakiś wynik, to można by napisać test, który ją wywołuje i sprawdza czy jej wynik zgadza się z rzeczywistością. Do takiego testu przygotowujesz 2 dodatkowe funkcje, jedną która generuje poprawne dane i drugą która generuje niepoprawne i puszczasz wyniki obu kilkaset razy przez twoją funkcje.

0

Nie rób takich wielkich ifów, przyklej to do funkcji

def foo(data)
    def doFoo(data):
        ...
    if data is not None:
        return (doFoo(data))

Nie rób 20 ifów do tego samego, możesz tu użyć słownika monthNumber : daysCount

Unikaj funkcji void, niech one zwracają wynik, client sobie je wyprintuje jak będzie chciał.

0

Poprawiłem te if'y oraz wrzuciłem to do funkcji. Wyszło mi coś takiego:

#! python3
# Date Detection - Checks if date is correct.
import re

date_regex = re.compile(r'([0|123]\d)/(\d{2})/(\d{4})')

def date_detection(date_input):
    while True:
        date_entered = date_regex.search(date_input)
        if date_entered is not None:
            month = date_entered.group(2)
            months = ['01', '02', '03', '04', '05', '06',
                      '07', '08', '09', '10', '11', '12']
            year = int(date_entered.group(3))
            if year > 3000 or year < 1000:
                print('Invalid year.')
                return False
            if month not in months:
                print('Invalid month.')
                return False
            day = int(date_entered.group(1))
            wrong_day = 'Invalid day.'
            months31 = ['01', '03', '05', '06', '08', '10', '12']
            months30 = ['04', '07', '09', '11']
            if month in months31:
                if day not in range(32):
                    print(wrong_day)
                    return False
            if month in months30:
                if day not in range(31):
                    print(wrong_day)
                    return False
            if month == '02':
                if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
                    if day not in range(30):
                        print(wrong_day)
                        return False
                else:
                    if day not in range(29):
                        print(wrong_day)
                        return False
            print('Date is valid.')
            return True
        else:
            print('Error. Wrong format.')
            return False

I pod spodem napisałem takie "manualne testy":

# Tests:

# 1) Year
# Invalid year: 3001 date_detection('15/12/3001') OK
# Invalid year: 999 date_detection('10/10/999') OK
# Invalid year, valid format: date_detection('10/10/0999') OK
# Valid: date_detection('10/05/2005') OK

# 2) Month
# Invalid month: date_detection('10/15/1999')

# 3) Day

# Feb:
# Valid: date_detection('29/02/2020') OK
# Invalid: date_detection('29/02/2021') OK

# months31 = ['01', '03', '05', '06', '08', '10', '12']
# Valid: date_detection('31/01/2000') OK
# Invalid: date_detection('32/01/2000') OK
# Valid: date_detection('31/03/2000') OK
# Invalid: date_detection('32/03/2000') OK
# Valid: date_detection('31/05/2000') OK
# Invalid: date_detection('32/05/2000') OK
# Valid: date_detection('31/06/2000') OK
# Invalid: date_detection('32/06/2000') OK
# Valid: date_detection('31/08/2000') OK
# Invalid: date_detection('32/08/2000') OK
# Valid: date_detection('31/10/2000') OK
# Invalid: date_detection('32/10/2000') OK
# Valid: date_detection('31/12/2000') OK
# Invalid: date_detection('32/12/2000') OK

# months30 = ['04', '07', '09', '11']
# Valid: date_detection('30/04/2020') OK
# Invalid: date_detection('31/04/2020') OK
# Valid: date_detection('30/07/2020') OK
# Invalid: date_detection('31/07/2020') OK
# Valid: date_detection('30/09/2020') OK
# Invalid: date_detection('31/09/2020') OK
# Valid: date_detection('30/11/2020') OK
# Invalid: date_detection('31/11/2020') OK

Czyli nawiązując do pisania testów, cała filozofia to jest napisać funkcje, które będą mi wrzucały do tej głównej funkcji (date_detection()) dane właściwe lub fałszywe tak jak to zrobiłem w ramach # Tests?

W sumie w takim rozwiązaniu jest szansa, że popełnię błąd i testy wyjdą źle a ja będę tego nieświadomy. Zdarzyło się Wam? Jak tego uniknąć?

1 użytkowników online, w tym zalogowanych: 0, gości: 1