PythonWebスクレイピング-スクレイパーを使用したテスト

この章では、PythonでWebスクレイパーを使用してテストを実行する方法について説明します。

前書き

大規模なWebプロジェクトでは、Webサイトのバックエンドの自動テストが定期的に実行されますが、フロントエンドのテストは頻繁にスキップされます。この背後にある主な理由は、Webサイトのプログラミングが、さまざまなマークアップおよびプログラミング言語のネットのようなものであるためです。ある言語の単体テストを書くことはできますが、相互作用が別の言語で行われている場合は困難になります。そのため、コードが期待どおりに実行されていることを確認するための一連のテストが必要です。

Pythonを使用したテスト

テストについて話しているとき、それはユニットテストを意味します。Pythonを使用したテストに深く踏み込む前に、単体テストについて知っておく必要があります。以下は、ユニットテストの特徴の一部です-

  • コンポーネントの機能の少なくとも1つの側面は、各単体テストでテストされます。

  • 各単体テストは独立しており、独立して実行することもできます。

  • ユニットテストは、他のテストの成功または失敗を妨げることはありません。

  • 単体テストは任意の順序で実行でき、少なくとも1つのアサーションが含まれている必要があります。

ユニットテスト-Pythonモジュール

ユニットテスト用のUnittestという名前のPythonモジュールには、すべての標準Pythonインストールが付属しています。それをインポートする必要があり、残りは次のことを行うunittest.TestCaseクラスのタスクです-

  • SetUp関数とtearDown関数は、unittest.TestCaseクラスによって提供されます。これらの関数は、各単体テストの前後に実行できます。

  • また、テストの合格または不合格を可能にするassertステートメントも提供します。

  • test_で始まるすべての関数を単体テストとして実行します。

この例では、Webスクレイピングと unittest。文字列「Python」を検索するためにウィキペディアのページをテストします。基本的に2つのテストを実行します。最初のテストでは、タイトルページが検索文字列と同じであるかどうか、つまり「Python」であるかどうか、2番目のテストでページにコンテンツdivがあることを確認します。

まず、必要なPythonモジュールをインポートします。WebスクレイピングにはBeautifulSoupを使用し、テストにはもちろんユニットテストを使用しています。

from urllib.request import urlopen
from bs4 import BeautifulSoup
import unittest

次に、unittest.TestCaseを拡張するクラスを定義する必要があります。グローバルオブジェクトbsは、すべてのテスト間で共有されます。unittestで指定された関数setUpClassがそれを実行します。ここでは、タイトルページをテストするための関数とページコンテンツをテストするための関数の2つの関数を定義します。

class Test(unittest.TestCase):
   bs = None
   def setUpClass():
      url = '<a target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Python">https://en.wikipedia.org/wiki/Python'</a>
      Test.bs = BeautifulSoup(urlopen(url), 'html.parser')
   def test_titleText(self):
      pageTitle = Test.bs.find('h1').get_text()
      self.assertEqual('Python', pageTitle);
   def test_contentExists(self):
      content = Test.bs.find('div',{'id':'mw-content-text'})
      self.assertIsNotNone(content)
if __name__ == '__main__':
   unittest.main()

上記のスクリプトを実行すると、次の出力が得られます-

----------------------------------------------------------------------
Ran 2 tests in 2.773s

OK
An exception has occurred, use %tb to see the full traceback.

SystemExit: False

D:\ProgramData\lib\site-packages\IPython\core\interactiveshell.py:2870:
UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)

Seleniumでのテスト

テストにPythonSeleniumを使用する方法について説明しましょう。Seleniumテストとも呼ばれます。両方のPythonunittest そして Selenium共通点はあまりありません。Seleniumは、ブラウザーの設計にばらつきがあるにもかかわらず、標準のPythonコマンドをさまざまなブラウザーに送信することを知っています。前の章ですでにSeleniumをインストールして使用したことを思い出してください。ここでは、Seleniumでテストスクリプトを作成し、それを自動化に使用します。

次のPythonスクリプトの助けを借りて、Facebookログインページを自動化するためのテストスクリプトを作成しています。選択した他のフォームとログインを自動化するために例を変更できますが、概念は同じです。

最初にWebブラウザーに接続するために、SeleniumモジュールからWebドライバーをインポートします-

from selenium import webdriver

次に、セレンモジュールからキーをインポートする必要があります。

from selenium.webdriver.common.keys import Keys

次に、Facebookアカウントにログインするためのユーザー名とパスワードを提供する必要があります

user = "[email protected]"
pwd = ""

次に、ChromeのWebドライバーへのパスを指定します。

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path=path)
driver.get("http://www.facebook.com")

次に、assertキーワードを使用して条件を確認します。

assert "Facebook" in driver.title

次のコード行を使用して、電子メールセクションに値を送信します。ここではIDで検索していますが、名前で検索すると次のようになります。driver.find_element_by_name("email")

element = driver.find_element_by_id("email")
element.send_keys(user)

次のコード行を使用して、パスワードセクションに値を送信します。ここではIDで検索していますが、名前で検索すると次のようになります。driver.find_element_by_name("pass")

element = driver.find_element_by_id("pass")
element.send_keys(pwd)

次のコード行は、電子メールとパスワードのフィールドに値を挿入した後、Enter / Loginを押すために使用されます。

element.send_keys(Keys.RETURN)

次に、ブラウザを閉じます。

driver.close()

上記のスクリプトを実行すると、Chrome Webブラウザーが開き、電子メールとパスワードが挿入され、ログインボタンをクリックされていることがわかります。

比較:ユニットテストまたはセレン

大規模なテストスイートで作業する場合は、ユニットの構文上の剛性が必要になるため、ユニットテストとセレンの比較は困難です。一方、Webサイトの柔軟性をテストする場合は、Seleniumテストが最初の選択肢になります。しかし、両方を組み合わせることができたらどうでしょうか。セレンをPythonユニットテストにインポートして、両方を最大限に活用できます。Seleniumを使用してWebサイトに関する情報を取得し、unittestはその情報がテストに合格するための基準を満たしているかどうかを評価できます。

たとえば、Facebookログインを自動化するために、上記のPythonスクリプトを次のように組み合わせて書き直しています。

import unittest
from selenium import webdriver

class InputFormsCheck(unittest.TestCase):
   def setUp(self):
      self.driver = webdriver.Chrome(r'C:\Users\gaurav\Desktop\chromedriver')
      def test_singleInputField(self):
      user = "[email protected]"
      pwd = ""
      pageUrl = "http://www.facebook.com"
      driver=self.driver
      driver.maximize_window()
      driver.get(pageUrl)
      assert "Facebook" in driver.title
      elem = driver.find_element_by_id("email")
      elem.send_keys(user)
      elem = driver.find_element_by_id("pass")
      elem.send_keys(pwd)
      elem.send_keys(Keys.RETURN)
   def tearDown(self):
      self.driver.close()
if __name__ == "__main__":
   unittest.main()