【Ruby/RSpec】テスト時はプライベートモードでseleniumを動作させる
こんにちは、しきゆらです。
少し前、レンタルサーバの支払いを忘れていて一瞬サイトが消えていました。
自分でもびっくりしました・・・。
さて今回は、というか今回もRSpecのお話。
ここ最近、お仕事で自分の書いている小さなスクリプトにテストがなくて怖いなーという思いが強くなりRSpecを書くことが多いので、その時のメモです。
最近書いているのは、Seleniumでとあるサイトで行っている操作を自動化するというもの。
どうしても外部サイトをあれこれするスクリプトを書いているとテストを書きにくいです。
ということで、直接サイトにあれこれする部分は最低限ログインできるかくらいしかかけていません。
どうするのがいいんでしょうか。
さて、Seleniumでブラウザを制御するときに困るのは、キャッシュやCookieなどの影響で挙動が変わること。
ログインしようとしても前回の残骸が残っていると何度も確かめることができない、なんていうこともあります。
そこで、タイトルの通りテストの時はプライベートモードで動いてほしいなーと思っていい感じに書く方法をあれこれ考えてできたものをメモしておきます。
テスト対象となるスクリプト
まずは、ブラウザ操作をまとめる部分から。
Seleniumを初期化するときに、Chromeのオプションを渡してあげると、普段使っているプロファイルと分けて使うことができます。
また、実際に実行するときはキャッシュ等残っていても問題ないので、そのように設定してあります。
なお、Chromeに渡すことができるフラグは以下のサイトにまとまっています。
https://peter.sh/experiments/chromium-command-line-switches/
class Browser
attr_reader :driver
def initialize
selenium_configures = [
"--user-data-dir=selenium_profile", # プロファイルのパス:./selenium_profile
"--profile-directory=Default", # プロファイルのデフォルトのものを使う
"--restore-last-session" # 前回のセッションを保持する
]
option = Selenium::WebDriver::Chrome::Options.new
selenium_configures.each do |config|
options.add_argument(config)
end
@driver = Selenium::WebDriver.for(:chrome, options: options)
end
# driverに対してごにょごにょする
end
ただ、こうしておくとオプションをテストの時に差し替えたりしにくいです。
ということで、オプションをメソッドに切り出します。
class Browser
attr_reader :driver
def initialize
option = Selenium::WebDriver::Chrome::Options.new
selenium_configures.each do |config|
options.add_argument(config)
end
@driver = Selenium::WebDriver.for(:chrome, options: options)
end
# 設定部分を切り出した
def selenium_configures
@selenium_configures ||= [
"--user-data-dir=selenium_profile", # プロファイルのパス:./selenium_profile
"--profile-directory=Default", # プロファイルのデフォルトのものを使う
"--restore-last-session" # 前回のセッションを保持する
]
end
# driverに対してごにょごにょする
end
こうしてあげると、RSpec側であれこれしやすくなります。
RSpec側のコード
プライベートモードでChromeを起動してあげるものと、そのほか諸々のオプションはこの辺。
[
"--incognito",
"--no-sandbox",
"--disable-dev-shm-usage"
]
こいつらを、切り出したメソッドのように渡してあげたい。
それでは、RSpec側のコードを書いて見ます。
まずは、本チャンコードのselenium_configures
の値を無視するように変更します。
RSpec.describe Browser do
let(:browser) { Browser.new }
let(:options) { Selenium::WebDriver::Chrome::Options.new }
before do
# すべてのBrowserインスタンスが`selenium_configures`メソッドをもち、[]を返す
allow_any_instance_of(Browser).to receive(:selenium_configures).and_return([])
end
end
ひとまず、切り出したメソッドを無効化しています。
基本的にはselenium_configures
の返り値をプライベートモードの設定に置き換えればいいのですが、
それだけだと、必要ない場面や、ここではさらにheadless
にしたい、ということもあるかもしれないので以下のように付けはずしできるようにします。
RSpec.shared_context "private" do
let(:options) { Selenium::WebDriver::Chrome::Options.new }
let(:private_config) do
[
"--incognito",
"--no-sandbox",
"--disable-dev-shm-usage"
]
end
before do
private_config.each {|config| options.add_argument(config)}
end
end
こんな感じで、Seleniumのオプションを設定する部分をshared_context
としてワンセットにしておきます。
あとは、必要なところで`include_context “private"`のようにしてあげれば、必要な場面でプライベートモードで動かすことができるようになりました。
まとめ
今回は、Seleniumで良しななタイミングだけプライベートモードで動かしたいときにうまいことする方法を考えてみました。
いろいろやろうと思えばできるような環境はそろっているんだなぁという印象でした。
そのうち、ヘッドレス版とかもメモしたいと思います。
今回は、ここまで。
おわり