Forum Testowania i AutomatyzacjiKategoria: PytanieZmiana zmiennej przy starcie testu z cmd
AvatarKatarzyna Kusiak zapytał 6 lat temu

Hej, 
Mam taki ‘kejs’.
Testy piszę w python +unittest +selenium.
Swoje testy puszczam z cmd przy pomocy komendy  ‘python -m unittest scripts.py’. Wszystko jest OK 🙂
Jednak w tej komendzie chciałabym podać również na jakim środowisku testy mają się odpalić, chodzi mi o sytuację, gdy w teście mam zdefiniowany URL do produkcji i do środowiska testowego i wpisując w komendzie np  ‘env=prod’ test odpala się na URL produkcyjnym, a w sytuacji gdy podaję ‘env=środowiskoTestowe ‘ testy odpalają się na URL testowego środowiska. 
Przekopałam trochę internet i jedyne co znalazłam to biblioteka argpars, jednak to też mi nie pomogło. Czy dla python +unittest +selenium da się w ogóle coś takiego zrobić ? W taki sam sposób chciałabym wskazywać na jakiej przeglądarce testy mają się odpalać i mam ten samym problem. 
Jakieś rozwiązanie dla takiego problemu lub jakaś podpwiedź ? 🙂
Pozdrawiam ! 

1 odpowiedzi
Krzysiek KijasKrzysiek Kijas Personel odpowiedział 6 lat temu

Hej,
Generalnie problem jest w tym, że wszystkie argumenty będą zgarniane przez bibliotekę unittest i nie ma prostej odp. Najlepiej jest użyć ustawień w zmiennych środowiskowych lub przechowywanych w pliku, co jest najlepszym multisystemowym rozwiązaniem 🙂
Przykład 1.
Z zapisem do pliku – stwórzmy pythonowy plik env_set.py

from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument("-e", "--environment", help="specify type of environment: test, dev, prod")
args = parser.parse_args()

ENV = ''
received_env = str(args.environment)

test_env = 'http://lolo-test.com'
dev_env = 'http://lolo-dev.com'
prod_env = 'http://lolo-prod.com'
if received_env:
    if received_env == 'test':
        ENV = test_env
    elif received_env == 'dev':
        ENV = dev_env
    elif received_env == 'prod':
        ENV = prod_env
    else:
        print(f'There is no environment like: {received_env}, setting up default test env: {test_env}')
        ENV = test_env
else:
    print(f'No environment specified, setting up default test env: {test_env}')
    ENV = test_env


with open('env.txt', 'w+') as file:
    file.write(ENV)
    print('saved')

i w samym teście np plik test_login.py

import unittest

class TestLogin(unittest.TestCase):
    ENV = ''

    def setUp(self):
        with open('env.txt') as f:
            ENV = f.readlines()
        self.base_url = ENV

    def test_logins_or_something(self):
        print(self.base_url)

Wywołanie
python env_set.py -e 'test' | python -m unittest test_login.py
Gdzie pierwszą część można wywołać tylko raz przed testem. To jest w mega uproszczeniu – dalej trzeba zaczytywanie z pliku URL dać do osobnej metody i już w każdym setUp wołać tą metodę.
Przykład 2.
Najprościej zrezygnować z używania unittest i odpalać bezpośrednio plik jak: python myTest.py wtedy możemy użyć dowolnych argumentów ale musimy uruchomić unittest w naszym odpalanym pliku.

import sys
import unittest


def env_set(environment):
    test_env = 'http://lolo-test.com'
    dev_env = 'http://lolo-dev.com'
    prod_env = 'http://lolo-prod.com'

    if environment:
        if environment == 'test':
            return test_env
        elif environment == 'dev':
            return dev_env
        elif environment == 'prod':
            return prod_env
        else:
            print(f'There is no environment like: {environment}, setting up default test env: {test_env}')
            return test_env
    else:
        print(f'No environment specified, setting up default test env: {test_env}')
        return test_env


class TestLogin(unittest.TestCase):
    ENV = ''

    def setUp(self):
        self.base_url = env_set(self.ENV)

    def test_logins_or_something(self):
        print(self.base_url)


if __name__ == "__main__":
    if len(sys.argv) > 1:
        TestLogin.ENV = sys.argv.pop()
    unittest.main()

Wywołując python testLogin test lub z innym argumentem otrzymasz odpowiednie środowisko. idąc dalej możesz w ten sam sposób użyć zaawansowanej parametryzacji.

Przykład 3.
Inny działający przykład przekazywania parametrów bezpośrednio do testów:

from argparse import ArgumentParser
import unittest

class TestingClass(unittest.TestCase):
    def test_on_my_custom_env(self):
        print(f"My env is: {args.env}")

parser = ArgumentParser()
parser.add_argument("-e", "--env", dest="env", help="Environment")
args = parser.parse_args()

if __name__ == "__main__":
    runner = unittest.TextTestRunner()
    my_test_class = unittest.TestLoader().loadTestsFromTestCase(TestingClass)
    runner.run(my_test_class)

Teraz, jeśli użyjemy komendy:
python unittest_sample.py --env prod
otrzymamy:

usage: unittest_sample.py [-h] [-e ENV]
unittest_sample.py: error: unrecognized arguments: prod
C:\projects\scripts>python unittest_sample.py --env prod
My env is: prod
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

ArgumentParser – jest to chyba najwygodniejszy sposób przekazywania i parsowani parametrów 😉 Nietrywialne może się wydawać wywołanie klasy testowej – nie można tutaj użyć unittest.main(), gdyż powoduje to wyświetlenie błędu o nierozpoznanych parametrach: unittest_sample.py: error: unrecognized arguments: --env. Może być to spowodowane faktem, że unittest.main() próbuje parsować wszystkie, w tym nasze, parametry i ich po prostu nie rozpoznaje.