2009-06-22 13 views
37

Mam moduł, który importuje unittest i ma kilka testcases. Chciałbym zaakceptować niektóre opcje wiersza poleceń (na przykład poniżej, nazwa pliku danych), , ale kiedy spróbuję przekazać opcję, otrzymuję komunikat "opcja -i nie rozpoznana". Czy jest możliwe, aby unittest + zapewnić opcje do aplikacji (uwaga: używam opcji optparse do obsługi opcji)? Dzięki.python, unittest: czy istnieje sposób przekazywania opcji wiersza poleceń do aplikacji

$ python test_app_data.py -i data_1.txt 

option -i not recognized 

=====================

follow-up: to jest realizacja proponowanego rozwiązania:

import cfg_master #has the optparse option-handling code 

... 

if __name__ == '__main__':  
    #add you app's options here... 
    options_tpl = ('-i', '--in_dir', '-o', '--out_dir') 
    del_lst = [] 
    for i,option in enumerate(sys.argv): 
     if option in options_tpl: 
      del_lst.append(i) 
      del_lst.append(i+1) 

    del_lst.reverse() 
    for i in del_lst: 
     del sys.argv[i] 

    unittest.main() 
+0

W ujęciu ogólnym, tak. W tym przypadku wydaje się, że odpowiedź w dużej mierze zależy od szczegółów, które nie zostały podane. –

+0

@jd. Twój "follow-up" powinien zostać opublikowany jako odpowiedź - twoje pytanie powinno zawierać tylko ... cóż ... pytanie. – user1251007

Odpowiedz

45

Opierając się na odpowiedź Alexa, to faktycznie dość łatwe do zrobienia przy użyciu argparse:

if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 
    parser.add_argument('--input', default='My Input') 
    parser.add_argument('filename', default='some_file.txt') 
    parser.add_argument('unittest_args', nargs='*') 

    args = parser.parse_args() 
    # TODO: Go do something with args.input and args.filename 

    # Now set the sys.argv to the unittest_args (leaving sys.argv[0] alone) 
    sys.argv[1:] = args.unittest_args 
    unittest.main() 

nie testowałem wszystkie flagi można przekazać do unittest, aby zobaczyć, czy pracują, czy nie, ale przejściu testu nazwy w działa, np:

python test.py --input=foo data.txt MyTest 

działa MyTest z foo i data.txt.

+3

Nice! Nawet lepiej, 'unittest.main()' akceptuje parametr argv, więc nie musisz zadzierać z globalnym sys.argv, np. tak jak: 'unit_argv = [sys.argv [0]] + args.unittest_args; unittest.main (argv = unit_argv) ' – wutz

+3

Zamiast tego możesz użyć' .parse_known_args() 'i nie musisz używać opcji' nargs = '*' '; zobacz [Python: uruchom unittest.TestCase bez wywoływania metody unittest.main()?] (http://stackoverflow.com/a/17259773) dla mojej wersji. –

+0

Połączyłem tę odpowiedź z pytaniem przywoływanym przez @MartijnPieters, ponieważ podejście to spodobało mi się. Jednak po zaimplementowaniu ta odpowiedź nie działała dla mnie podczas przekazywania flag (--failfast i --catch), więc powróciłem do odpowiedzi Martijna. –

31

W sekcji if __name__ == '__main__':, których nie jesteś pokazując nam, musisz optparse a następnie del sys.argv[1:] zanim przejdzie kontrolę do kodu unittest, tak że ten ostatni kod nie próbować interpretować opcji wiersza poleceń ponownie kiedy yo już z nimi poradziłeś. (Trochę trudniej jest mieć niektóre opcje własnego i również przekazać trochę do unittest, choć można to zrobić, jeśli masz tak złożone potrzeby).

+0

świetnie, dzięki; aby potwierdzić: najpierw pozwolić optparse na obsługę (prawdopodobnie wielu i zmiennych) opcji aplikacji, a następnie usunąć je z sys.argv, a ostatecznie pozwolić na przejęcie przez unittest? –

+0

@jd yep, to jest sedno! –

+0

Świetne, dzięki Alex! Nie mogłem tego w ogóle rozpracować: P – Skilldrick

-7

Nie powinieneś brać argumentów i opcji, aby uruchamiać unittests, ponieważ uruchamiasz je w różnych, mniej przewidywalnych warunkach w ten sposób. Powinieneś dowiedzieć się, dlaczego musisz uruchamiać testy z różnymi danymi i sprawić, że zestaw testów będzie na tyle kompletny, aby pokryć cały zbiór danych, nie za każdym razem uruchamiając go inaczej.

+0

otrzymuję cotygodniowe raporty danych (pliki); Chciałbym przekazać te nowe raporty do unittests, przed wygenerowaniem publicznych raportów. Jeśli z jakiegoś powodu zmieniła się struktura lub typ danych (np. Dodano nowe pole kolumn, zakres danych zmieniono, a błąd został odsłonięty) Chciałbym je złapać za pomocą testów. Mam nadzieję, że to ma sens. –

+2

pewnie, ale to jest sprawdzanie poprawności danych, a nie unieważnianie. – ironfroggy

+2

Co należy zrobić, aby pominąć test warunkowy?Wszystkie moje przypadki testowe uruchamiam, wykonując test testowy Unittest, ale dobrze byłoby mieć adnotacje na temat niektórych testów, takich jak @skipUnless ('- full' w sys.argv), dzięki czemu mogę mieć łatwy sposób w linii poleceń wszystkich testów lub tylko niektórych. –

1

Dla małych aplikacjach autonomicznych, używam początkową opcję wartowniczy (-t) i wywołać unittest.main() przed wywołaniem argparse.ArgumentParser()

if __name__ == "__main__": 
    if len(sys.argv) > 1 and sys.argv[1] in ["-t", "--test"]: 
     del(sys.argv[1]) 
     sys.exit(unittest.main()) # pass sys.argv[ 

    p = argparse.ArgumentParser() 
    . . . 
Powiązane problemy