2015-03-15 1 views
0

J'essaie actuellement d'utiliser la version Python de avec le framework de test Pytest pour faire des tests d'automatisation de web applications. Je suis tombé sur un problème en essayant de faire une requête HTTP moqueuse dans mon code Selenium. J'ai écrit un module intitulé "Selenium_WebDriver_Mocking_test.py" où je navigue vers le site officiel de Python et remplis un terme de recherche dans la boîte de recherche en haut de la page, puis appuie sur Entrée pour aller à la page des résultats. Le code fonctionne parfaitement quand je n'essaie pas de me moquer de quoi que ce soit. En supposant que vous avez à la fois Sélénium et Pytest installé, vous pouvez l'exécuter à partir de l'interface de ligne de commande en tapant la commande suivante:Requêtes de simulation envoyées par le Selenium WebDriver en Python et ayant les fausses réponses affichées dans l'instance de navigateur pilotée par le pilote à la place

py.test full/path/to/module/Selenium_WebDriver_Mocking_test.py 

ou en tapant la commande suivante:

python -m pytest full/path/to/module/Selenium_WebDriver_Mocking_test.py 

Le code est illustré ci-dessous.

Page
# contents of Selenium_WebDriver_Mocking_test.py 

import selenium.webdriver 
import selenium.webdriver.common.keys as common 
import selenium.webdriver.support.ui as user_interface 
import selenium.webdriver.support.expected_conditions as expected_conditions 
import selenium.webdriver.common.by as locate 
import re 
import pytest 


browsers = { 
    "firefox_driver": selenium.webdriver.Firefox(), 
    "chrome_driver": selenium.webdriver.Chrome() 
} 

website_homepage_url = "http://www.python.org" 
title_1 = "Welcome to Python.org" 


# Test set-up and tear down functions 
@pytest.fixture(scope = 'session', params = browsers.keys()) 
def browser(request): 
    driver = browsers[request.param] 
    driver.maximize_window() 
    def close_browser(): 
     driver.quit() 
    request.addfinalizer(close_browser) 
    return driver 


@pytest.mark.parametrize(
    "search_term", 
    [ 
     ("pycon"), 
     ("tkinter"), 
     ("django"), 
    ] 
) 
def test_mocking_get_request_works_properly(search_term, browser): 
    browser.get(website_homepage_url) 
    assert title_1 in browser.title     # Check you are on the right page 
    search_text_box = browser.find_element_by_css_selector("#id-search-field") 
    search_text_box.send_keys(search_term) 
    search_text_box.send_keys(common.Keys.RETURN) 
    search_page_title = user_interface.WebDriverWait(browser, 10).until(
      expected_conditions.visibility_of_element_located(
       (locate.By.XPATH, "//h2[contains(., 'Search')]"))) 
    assert search_page_title.is_displayed()   # Check you are on the right page 

J'ai alors écrit quelques HTML pour un résultats faux et ont essayé d'utiliser l'outil HTTPretty écrit par Gabriel Falcao pour retourner cette page comme une réponse qui apparaît dans le navigateur au lieu de la vraie page de résultats Python.org. Le code modifié est indiqué ci-dessous.

# contents of Selenium_WebDriver_Mocking_test.py 

import selenium.webdriver 
import selenium.webdriver.common.keys as common 
import selenium.webdriver.support.ui as user_interface 
import selenium.webdriver.support.expected_conditions as expected_conditions 
import selenium.webdriver.common.by as locate 
import time 
import httpretty 
import re 
import pytest 


browsers = { 
    "firefox_driver": selenium.webdriver.Firefox(), 
    "chrome_driver": selenium.webdriver.Chrome() 
} 

website_homepage_url = "http://www.python.org" 
title_1 = "Welcome to Python.org" 

request_url_pattern = re.compile('https://www.python.org/search/.*') 
response_html_lines = ["<!DOCTYPE html>", 
         "<html>", 
         "<head>", 
         "<title>Welcome to my fun page</title>", 
         "<meta charset=\"UTF-8\">" 
         "</head>", 
         "<body>", 
         "<h2>Search Python.org</h2>", 
         "<h2>So far so good (^_^)</h2>", 
         "<img src = \"http://i.imgur.com/EjcKmEj.gif\">", 
         "</body>", 
         "</html>"] 
fake_response_html = "\n".join(response_html_lines) 


# Test set-up and tear down functions 
@pytest.fixture(scope = 'session', params = browsers.keys()) 
def browser(request): 
    driver = browsers[request.param] 
    driver.maximize_window() 
    def close_browser(): 
     driver.quit() 
    request.addfinalizer(close_browser) 
    return driver 


@pytest.mark.parametrize(
    "search_term", 
    [ 
     ("pycon"), 
     ("tkinter"), 
     ("django"), 
    ] 
) 
def test_mocking_get_request_works_properly(search_term, browser): 
    httpretty.enable() 
    httpretty.register_uri(httpretty.GET, 
          request_url_pattern, 
          body = fake_response_html) 
    browser.get(website_homepage_url) 
    assert title_1 in browser.title     # Check you are on the right page 
    search_text_box = browser.find_element_by_css_selector("#id-search-field") 
    search_text_box.send_keys(search_term) 
    search_text_box.send_keys(common.Keys.RETURN) 
    search_page_title = user_interface.WebDriverWait(browser, 10).until(
      expected_conditions.visibility_of_element_located(
       (locate.By.XPATH, "//h2[contains(., 'Search')]"))) 
    assert search_page_title.is_displayed()   # Check you are on the right page 
    time.sleep(10) 
    httpretty.disable() 
    httpretty.reset() 

Cette approche n'a pas fonctionné et je reçu le message suivant dans le journal d'une des itérations de test:

C:\Python27\python.exe "C:\Program Files (x86)\JetBrains\PyCharm 

Community Edition 4.0.4\helpers\pycharm\pytestrunner.py" -p pytest_teamcity C:/Users/johnsmith/Computer_Code/Python/Automation_Testing/Selenium_WebDriver_Mocking_test.py 
Testing started at 10:10 ... 
============================= test session starts ============================= 
platform win32 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4 
plugins: xdist 
collected 6 items 

../../../../../../Users/johnsmith/Computer_Code/Python/Automation_Testing/Selenium_WebDriver_Mocking_test.py F 
search_term = 'pycon' 
browser = <selenium.webdriver.firefox.webdriver.WebDriver object at 0x0000000002E67EB8> 

    @pytest.mark.parametrize(
     "search_term", 
     [ 
      ("pycon"), 
      ("tkinter"), 
      ("django"), 
     ] 
    ) 
    def test_mocking_get_request_works_properly(search_term, browser): 
     httpretty.enable() 
     httpretty.register_uri(httpretty.GET, 
           request_url_pattern, 
           body = fake_response_html)  
>  browser.get(website_homepage_url) 

C:\Users\johnsmith\Computer_Code\Python\Automation_Testing\Selenium_WebDriver_Mocking_test.py:70: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py:187: in get 
    self.execute(Command.GET, {'url': url}) 
C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py:173: in execute 
    response = self.command_executor.execute(driver_command, params) 
C:\Python27\lib\site-packages\selenium\webdriver\remote\remote_connection.py:349: in execute 
    return self._request(command_info[0], url, body=data) 
C:\Python27\lib\site-packages\selenium\webdriver\remote\remote_connection.py:379: in _request 
    self._conn.request(method, parsed_url.path, body, headers) 
C:\Python27\lib\httplib.py:973: in request 
    self._send_request(method, url, body, headers) 
C:\Python27\lib\httplib.py:1007: in _send_request 
    self.endheaders(body) 
C:\Python27\lib\httplib.py:969: in endheaders 
    self._send_output(message_body) 
C:\Python27\lib\httplib.py:829: in _send_output 
    self.send(msg) 
C:\Python27\lib\httplib.py:791: in send 
    self.connect() 
C:\Python27\lib\httplib.py:772: in connect 
    self.timeout, self.source_address) 
C:\Python27\lib\site-packages\httpretty\core.py:477: in create_fake_connection 
    s.connect(address) 
C:\Python27\lib\site-packages\httpretty\core.py:311: in connect 
    self.truesock.connect(self._address) 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

name = 'connect', self = <socket._socketobject object at 0x000000000385F9A0> 
args = (('127.0.0.1', '49952'),) 

    def meth(name,self,*args): 
>  return getattr(self._sock,name)(*args) 
E  TypeError: an integer is required 

C:\Python27\lib\socket.py:224: TypeError 

J'ai aussi essayé d'utiliser l'outil de réponses écrites par David Cramer. Bien que cela n'ait renvoyé aucune erreur, il n'a rien fait du tout et le test s'est déroulé comme si aucune moquerie n'avait eu lieu. Ma question est la suivante: y a-t-il un moyen en Python de se moquer des requêtes envoyées par le Selenium WebDriver et d'avoir les faux corps de réponse affichés dans l'instance du navigateur pilotée par le pilote à la place? Toute aide est appréciée.

Répondre

0

Pour votre cas, vous ne pouvez pas utiliser une approche de moquerie «standard» car vous interférez de toute évidence avec la communication webdriver. Au lieu de cela, je vous suggère d'utiliser https://pypi.python.org/pypi/pytest-localserver alors là, vous exécutez réellement le serveur local sur un port aléatoire et le serveur ce qui est nécessaire pour vous. J'utilise cette technique pour les tests pytest-écharde (que je vous suggère également d'utiliser pour vos tests en fait) Ici vous pouvez voir comment tout cela fonctionne: https://github.com/pytest-dev/pytest-splinter/blob/master/tests/test_plugin.py

dans le cas où vous utiliserez pytest-écharde votre code ressembler à:

"""Testing fake html page with pytest-splinter.""" 
import pytest 
from pytest_localserver.http import WSGIServer 
import urlparse 

browsers = [ 
    "firefox", 
    "chrome" 
] 

title_1 = "Welcome to my fun page" 

response_html = """ 
    <!DOCTYPE html> 
    <html> 
    <head> 
    <title>Welcome to my fun page</title> 
    <meta charset="UTF-8"> 
    </head> 
    <body> 
    <h2>Search Python.org</h2> 
    <form action="/"> 
     <input id="id-search-field" name="search" /> 
    </form> 
    </body> 
    </html> 
    """ 


def simple_app(environ, start_response): 
    """Simplest possible WSGI application.""" 
    status = '200 OK' 
    response_headers = [('Content-type', 'text/html')] 
    start_response(status, response_headers) 
    query = urlparse.parse_qs(environ['QUERY_STRING']) 
    if 'search' in query: 
     search_term = query['search'][0] 
     return [""" 
     <!DOCTYPE html> 
     <html> 
     <body> 
     <h2>So far so good (^_^)</h2> 
     <p>You searched for: "{search_term}"</p> 
     <img src="http://i.imgur.com/EjcKmEj.gif"> 
     </body> 
     </html> 
     """.format(search_term=search_term)] 
    else: 
     return [response_html] 


@pytest.yield_fixture 
def testserver(): 
    """Define the testserver.""" 
    server = WSGIServer(application=simple_app) 
    server.start() 
    yield server 
    server.stop() 


@pytest.fixture(params=browsers) 
def splinter_webdriver(request): 
    return request.param 


@pytest.mark.parametrize(
    "search_term", 
    [ 
     ("pycon"), 
     ("tkinter"), 
     ("django"), 
    ] 
) 
def test_get_request_works_properly(search_term, browser, testserver): 
    browser.visit(testserver.url) 
    assert title_1 in browser.title     # Check you are on the right page 
    assert browser.find_by_xpath("//h2[contains(., 'Search')]").visible # Check you are on the right page 
    browser.find_by_css("#id-search-field").fill(search_term + '\r') 
    assert browser.find_by_xpath(
     """//p[contains(., 'You searched for: "{search_term}"')]""".format(search_term=search_term)).visible 
    assert browser.find_by_xpath(
     "//img[contains(@src, 'i.imgur.com/EjcKmEj.gif')]").visible # Check you get results 

exigences que j'ai utilisé pour cela sont:

pytest pytest-écharde pytest-localserver

(tous les plus récents)

+0

Merci pour votre réponse. J'ai installé pytest-localserver et j'ai ensuite essayé de suivre les exemples donnés et votre exemple mais sans succès. Chaque fois que je tape httpserver dans mon éditeur IDE, j'obtiens une erreur de référence non résolue. Pourriez-vous préciser comment implémenter votre méthode dans le fichier Selenium_WebDriver_Mocking_test.py que j'ai posté ci-dessus. –

+0

Je vais avoir un peu de temps plus tard aujourd'hui pour écrire un exemple pour vous –

+0

mais pour l'instant - votre IDE ne devrait pas essayer de résoudre les appareils du tout.Les appareils sont fournis par des machines pytest, il suffit de les utiliser comme arguments de la fonction - comme dans mon test. –