LoginSignup
2
4

Web画面のエビデンス取得の自動化

Last updated at Posted at 2023-11-21

画面テストの自動化ツールを使っていないプロジェクトに参画した。手動でテストは大変でした。エビデンス取得が楽になるプログラムをpythonで書いてみた。ほとんど参考ページのまんまですが。。。

はじめに

画面テストは以下の作業がある。2,3,4を2クリックで自動化してみる。
1.対象の画面まで遷移
2.画面キャプチャ取得(windows + shift + s -> 対象範囲をドラッグ)
3.Excelのシートに貼り付け(Excelに切り替えて -> ctrl + v)
4.画像サイズを適当なサイズに縮小(画像選択 -> ドラッグで縮小)

検討内容

1.スクリーンショットを撮る範囲を指定する
2.スクリーンショットを取得する
3.完成プログラム
4.おまけ(応用編)

1. スクリーンショットを撮る範囲を指定する

    リンクページの以下の部分だけ変更してみた
    # 範囲の確認
    print(f"{left_up_x} {left_up_y} {right_down_x-left_up_x} {right_down_y-left_up_y}")  
出力結果:242 260 957 748

2. スクリーンショットを取得する

座標はクリックイベントで取得せず引数から取得するように変更した
def main(args):
    with mouse.Listener(on_click=on_click) as listener:
        listener.join()
    # スクリーンショットを保存
    pyautogui.screenshot("screenshot.png", region=(args.left_up_x, args.left_up_y, args.right_down_x, args.right_down_y)) 
    
on_clickはウインドウ切り替えのための1回と画面選択をするための1回に変更した
def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウの切り替え
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは終了
        else:
            return False

▼ 実行結果
スクリーンショットがpythonプログラムと同じフォルダに保存されています。
evidence.png

▼ 画像をエクセルに貼り付ける
openpyxlモジュールを使ってExcelを操作する。
スクリーンショット画像を読み込んで、Excelをオープンし、シート選択し、指定セルに貼り付ける。

3 完成プログラム

短いプログラムで仕事効率を上げます!

# evidence.py
import os
import argparse
from pynput import mouse
import pyautogui
import win32clipboard
import io
import sys
import openpyxl
from openpyxl.drawing.image import Image
from openpyxl.utils import get_column_letter

# //////////////////////////////////////////////////
# プログラムの説明
#   ブラウザ画面の指定範囲をスクリーンショットする
#   スクリーンショットをエクセルに貼り付ける
# 実行準備
#   Excelファイルは閉じておく
#   実行ファイルのあるフォルダでpowershellを開く
#   実行ファイル名と引数を入力してEnter
# 引数の確認方法
#   実行ファイル名 -h
# 実行例
#   python .\evidence.py 242 260 957 748 Book1.xlsx Sheet11 B3
# 実行後の画面操作方法
#   1回目のクリックでブラウザを選択
#   2回目のクリックでエビデンスの画面を選択
# 結果確認方法
#  Excelファイルを開いて画像が貼られていることを確認
# //////////////////////////////////////////////////

# 初期値
num_press = 0
last_height_size = 480

def main(args):
    with mouse.Listener(on_click=on_click) as listener:
        listener.join()
    # スクリーンショットを保存
    pyautogui.screenshot("screenshot.png", region=(args.left_up_x, args.left_up_y, args.right_down_x, args.right_down_y)) 
    copy_paste(args)

def copy_paste(args): 
    # スクリーンショット画像を取得
    img = Image(os.path.join(".\\","screenshot.png"))
    # 画像サイズ縮小
    width_size = img.width
    height_size = img.height
    zoom_percentage = last_height_size / height_size
    img.width = width_size * zoom_percentage
    img.height = last_height_size
    #すでに存在するExcelワークブックを読み込む 
    wb = openpyxl.load_workbook(args.book_name, read_only=False)
    #ワークブック内のアクティブなシートを取得
    ws = wb.active
    # 画像貼り付け
    ws.add_image(img, f"{args.select_range}")
    # 保存
    wb.save(args.book_name)
   
def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウの切り替え
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは終了
        else:
            return False

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("left_up_x", help="X軸始点", type=int)
    parser.add_argument("left_up_y", help="Y軸始点", type=int)
    parser.add_argument("right_down_x", help="X軸終点", type=int)
    parser.add_argument("right_down_y", help="Y軸終点", type=int)
    parser.add_argument("book_name", help="使用する既存のExcelファイル名", type=str)
    parser.add_argument("sheet_name", help="使用する既存のシート名", type=str)
    parser.add_argument("select_range", help="貼り付けるセル", type=str)
    args = parser.parse_args()
    main(args)

▼ 以下の引数で実行

python .\evidence.py 242 260 957 748 test.xlsx test1 B3

▼ 実行結果
引数で指定したB3に貼り付けられています。
2023-11-21 204410.png

4 おまけ

一回の実行で繰り返しエビデンスを取得します。

毎回貼り付け位置を指定編

# getEvidenceRepeatManual.py
import os
import argparse
from pynput import mouse
import pyautogui
import win32clipboard
import io
import sys
import openpyxl
from openpyxl.drawing.image import Image

# //////////////////////////////////////////////////
# プログラムの説明
#   Excelの貼り付け位置を毎回指定してエビデンスを取得する
# 実行準備
#   Excelファイルは閉じておく
#   実行ファイルのあるフォルダでpowershellを開く
#   実行ファイル名と引数を入力してEnter
# 引数の確認方法
#   実行ファイル名 -h
# 実行例
#   python .\getEvidenceRepeat.py 242 260 957 748 Book1.xlsx Sheet11
# 実行後の画面操作方法
#   ①「続行する場合はExcelの貼り付け位置のRangeを入力してください。終了する場合はendを入力してください」
#      このメッセージが表示された時に取得対象の画面を開くことをお勧めする。
#   ②「対象画面を表示してクリックしてください」
    このメッセージが表示された時にウィンドウを表示して画面をクリックする
#     ※操作は2クリックで行う必要がある。
#      1回目のクリックはウインドウ選択、2回目のクリックは画像選択
#   ③①~②を繰り返す。またはendを入力して終了する。
# 結果確認方法
#  Excelファイルを開いて画像が貼られていることを確認
# Error
#   PermissionError: [Errno 13] Permission denied⇒Excelファイルが開いている
#   KeyError: "There is no item named '[Content_Types].xml' in the archive"⇒ファイルが壊れている
# //////////////////////////////////////////////////

# 定数
SCREENSHOT = "screenshot.png" # 一時画像ファイル名
# 初期値
num_press = 0
last_height_size = 480

def main(args):   
    input_val = input("続行する場合はExcelの貼り付け位置のRangeを入力してください。終了する場合はendを入力してください\n") 
    while True:
     if input_val == "end":
      break
     else:
      print("対象画面を表示してクリックしてください\n")
      with mouse.Listener(on_click=on_click) as listener:
        listener.join()
      screenshot(args, input_val)
      input_val = input("続行する場合はExcelのRangeを入力してください。終了する場合はendを入力してください\n")   
        
def screenshot(args, target_range):
    global num_press
    # スクリーンショットを保存
    pyautogui.screenshot(SCREENSHOT, region=(args.left_up_x, args.left_up_y, args.right_down_x, args.right_down_y)) 
    copy_paste(args, target_range)
    num_press = 0

def copy_paste(args, target_range): 
    # スクリーンショット画像を取得
    img = Image(os.path.join(".\\",SCREENSHOT))
    # 画像サイズ調整
    width_size = img.width
    height_size = img.height
    zoom_percentage = last_height_size / height_size
    img.width = width_size * zoom_percentage
    img.height = last_height_size
    #すでに存在するExcelワークブックを読み込む 
    wb = openpyxl.load_workbook(args.book_name, read_only=False)
    #ワークブック内のアクティブなシートを取得
    ws = wb.active
    # 画像貼り付け
    ws.add_image(img, f"{target_range}")
    # 保存
    wb.save(args.book_name)

def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウの切り替え
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは終了
        else:
            return False

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("left_up_x", help="X軸始点", type=int)
    parser.add_argument("left_up_y", help="Y軸始点", type=int)
    parser.add_argument("right_down_x", help="X軸終点", type=int)
    parser.add_argument("right_down_y", help="Y軸終点", type=int)
    parser.add_argument("book_name", help="使用する既存のExcelファイル名", type=str)
    parser.add_argument("sheet_name", help="使用する既存のシート名", type=str)
    args = parser.parse_args()
    main(args)

▼ 実行

PS C:\Users\USER\Documents\python> python .\getEvidenceRepeatManual.py 242 260 957 748 test.xlsx test
続行する場合はExcelの貼り付け位置のRangeを入力してください。終了する場合はendを入力してください
B2
対象画面を表示してクリックしてください

続行する場合はExcelのRangeを入力してください。終了する場合はendを入力してください
S25
対象画面を表示してクリックしてください

続行する場合はExcelのRangeを入力してください。終了する場合はendを入力してください
end

▼ 結果

貼り付け位置を自動計算 縦編

# getEvidenceRepeatZ.py
import os
import argparse
from pynput import mouse
import pyautogui
import win32clipboard
import io
import sys
import openpyxl
from openpyxl.drawing.image import Image
from openpyxl.utils import get_column_letter
import re

# //////////////////////////////////////////////////
# プログラムの説明
#   画面の指定範囲をスクリーンショットし、
#   引数で指定したRangeから自動計算して縦位置に貼り付けを繰り返し行う。
# 実行準備
#   貼り付けるシートのセルのサイズは縦36px,横36pxにする
#   Excelファイルは閉じておく
#   実行ファイルのあるフォルダでpowershellを開く
#   実行ファイル名と引数を入力してEnter
# 引数の確認方法
#   実行ファイル名 -h
# 実行例
#   python .\getEvidenceRepeat.py 242 260 957 748 Book1.xlsx Sheet11 B3
# 実行後の画面操作方法
#   ①「続行する場合はenterしてください。終了する場合はendを入力してください」
#      このメッセージが表示された時に取得対象の画面を開くことをお勧めする。
#   ②「対象画面を表示してクリックしてください」
    このメッセージが表示された時にウィンドウを表示して画面をクリックする
#     ※操作は2クリックで行う必要がある。
#      1回目のクリックはウインドウ選択、2回目のクリックは画像選択
#   ③①~②を繰り返す。またはendを入力して終了する。
# 結果確認方法
#  Excelファイルを開いて画像が貼られていることを確認
# Error
#   PermissionError: [Errno 13] Permission denied⇒Excelファイルが開いている
#   KeyError: "There is no item named '[Content_Types].xml' in the archive"⇒ファイルが壊れている
# //////////////////////////////////////////////////

# 定数
ROW_CALC = 24 # 画像サイズから行数に変換する値
COLUMN_CALC = 24 # 画像サイズから列数に変換する値
ROW_SPACE = 1 # 画像との間隔(縦)
COLUMN_SPACE = 1 # 画像との間隔(横)
SCREENSHOT = "screenshot.png" # 一時画像ファイル名
# 初期値
num_press = 0
last_height_size = 480
range = []
count = 0

def main(args):   
    global range, count
    input_val = input("続行する場合はenterしてください。終了する場合はendを入力してください\n") 
    while True:
     if input_val == "end":
      break
     else:
      count += 1
      print("対象画面を表示してクリックしてください\n")
      with mouse.Listener(on_click=on_click) as listener:
        listener.join()
      if len(range) == 0:
         range = split_cell(args.target_range)
      screenshot(args)      
      input_val = input("続行する場合はenterしてください。終了する場合はendを入力してください\n")   
        
def screenshot(args):
    global num_press, count
    # スクリーンショットを保存
    pyautogui.screenshot(SCREENSHOT, region=(args.left_up_x, args.left_up_y, args.right_down_x, args.right_down_y)) 
    copy_paste(args)
    num_press = 0

def copy_paste(args): 
    global range, count
    # スクリーンショット画像を取得
    img = Image(os.path.join(".\\",SCREENSHOT))
    # 画像サイズ調整
    width_size = img.width
    height_size = img.height
    zoom_percentage = last_height_size / height_size
    img.width = width_size * zoom_percentage
    img.height = last_height_size
    #すでに存在するExcelワークブックを読み込む 
    wb = openpyxl.load_workbook(args.book_name, read_only=False)
    #ワークブック内のアクティブなシートを取得
    ws = wb.active
    # 画像貼り付け
    ws.add_image(img, f"{get_column_letter(int(range[1]))}{range[0]}")
    # 保存
    wb.save(args.book_name)
    # 次のレンジを取得
    get_next_range(img)   

def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウの切り替え
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは終了
        else:
            return False
        
def get_next_range(img):
    global range, count
    row_num = int(((img.height) // ROW_CALC + ROW_SPACE))
    col_num = int((img.width) // COLUMN_CALC + COLUMN_SPACE)
    if count % 2 == 0:
     # Vertical
     range[0] = str(row_num * int(count/ 2))
     range[1] = str(int(range[1]) - col_num)
    elif count % 2 == 1:
     # Horizontal
     range[1] = str(col_num + int(range[1]))

def split_cell(target_range):
    # rangeの列の文字列を取得
    column = re.search(r"[A-Z]+",target_range).group()
    # rangeの行の数字を取得
    row = target_range[re.search(r"[0-9]+", target_range).start():]
    # rangeの列の文字列から列番号を取得
    col = 0
    for i, val in enumerate(list(column)):
       col += pow(26, len(column) - i - 1) * (ord(val) - ord('A') + 1)
    return [row,col]

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("left_up_x", help="X軸始点", type=int)
    parser.add_argument("left_up_y", help="Y軸始点", type=int)
    parser.add_argument("right_down_x", help="X軸終点", type=int)
    parser.add_argument("right_down_y", help="Y軸終点", type=int)
    parser.add_argument("book_name", help="使用する既存のExcelファイル名", type=str)
    parser.add_argument("sheet_name", help="使用する既存のシート名", type=str)
    parser.add_argument("target_range", help="最初のセル", type=str)
    args = parser.parse_args()
    main(args)

▼ 実行

PS C:\Users\USER\Documents\python> python .\getEvidenceRepeatAutoI.py 242 260 957 748 test.xlsx test B2
続行する場合はenterしてください。終了する場合はendを入力してください

対象画面を表示してクリックしてください

続行する場合はenterしてください。終了する場合はendを入力してください

対象画面を表示してクリックしてください

続行する場合はenterしてください。終了する場合はendを入力してください
end

▼ 結果

貼り付け位置を自動計算 Z編

# getEvidenceRepeatZ.py
import os
import argparse
from pynput import mouse
import pyautogui
import win32clipboard
import io
import sys
import openpyxl
from openpyxl.drawing.image import Image
from openpyxl.utils import get_column_letter
import re

# //////////////////////////////////////////////////
# プログラムの説明
#   画面の指定範囲をスクリーンショットし、
#   引数で指定したRangeから自動計算してレイアウトZで貼り付けを繰り返し行う。
# 実行準備
#   貼り付けるシートのセルのサイズは縦36px,横36pxにする
#   Excelファイルは閉じておく
#   実行ファイルのあるフォルダでpowershellを開く
#   実行ファイル名と引数を入力してEnter
# 引数の確認方法
#   実行ファイル名 -h
# 実行例
#   python .\getEvidenceRepeat.py 242 260 957 748 Book1.xlsx Sheet11 B3
# 実行後の画面操作方法
#   ①「続行する場合はenterしてください。終了する場合はendを入力してください」
#      このメッセージが表示された時に取得対象の画面を開くことをお勧めする。
#   ②「対象画面を表示してクリックしてください」
    このメッセージが表示された時にウィンドウを表示して画面をクリックする
#     ※操作は2クリックで行う必要がある。
#      1回目のクリックはウインドウ選択、2回目のクリックは画像選択
#   ③①~②を繰り返す。またはendを入力して終了する。
# 結果確認方法
#  Excelファイルを開いて画像が貼られていることを確認
# Error
#   PermissionError: [Errno 13] Permission denied⇒Excelファイルが開いている
#   KeyError: "There is no item named '[Content_Types].xml' in the archive"⇒ファイルが壊れている
# //////////////////////////////////////////////////

# 定数
ROW_CALC = 24 # 画像サイズから行数に変換する値
COLUMN_CALC = 24 # 画像サイズから列数に変換する値
ROW_SPACE = 1 # 画像との間隔(縦)
COLUMN_SPACE = 1 # 画像との間隔(横)
SCREENSHOT = "screenshot.png" # 一時画像ファイル名
# 初期値
num_press = 0
last_height_size = 480
range = []
count = 0

def main(args):   
    global range, count
    input_val = input("続行する場合はenterしてください。終了する場合はendを入力してください\n") 
    while True:
     if input_val == "end":
      break
     else:
      count += 1
      print("対象画面を表示してクリックしてください\n")
      with mouse.Listener(on_click=on_click) as listener:
        listener.join()
      if len(range) == 0:
         range = split_cell(args.target_range)
      screenshot(args)      
      input_val = input("続行する場合はenterしてください。終了する場合はendを入力してください\n")   
        
def screenshot(args):
    global num_press, count
    # スクリーンショットを保存
    pyautogui.screenshot(SCREENSHOT, region=(args.left_up_x, args.left_up_y, args.right_down_x, args.right_down_y)) 
    copy_paste(args)
    num_press = 0

def copy_paste(args): 
    global range, count
    # スクリーンショット画像を取得
    img = Image(os.path.join(".\\",SCREENSHOT))
    # 画像サイズ調整
    width_size = img.width
    height_size = img.height
    zoom_percentage = last_height_size / height_size
    img.width = width_size * zoom_percentage
    img.height = last_height_size
    #すでに存在するExcelワークブックを読み込む 
    wb = openpyxl.load_workbook(args.book_name, read_only=False)
    #ワークブック内のアクティブなシートを取得
    ws = wb.active
    # 画像貼り付け
    ws.add_image(img, f"{get_column_letter(int(range[1]))}{range[0]}")
    # 保存
    wb.save(args.book_name)
    # 次のレンジを取得
    get_next_range(img)   

def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウの切り替え
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは終了
        else:
            return False
        
def get_next_range(img):
    global range, count
    row_num = int(((img.height) // ROW_CALC + ROW_SPACE))
    col_num = int((img.width) // COLUMN_CALC + COLUMN_SPACE)
    if count % 2 == 0:
     # Vertical
     range[0] = str(row_num * int(count/ 2))
     range[1] = str(int(range[1]) - col_num)
    elif count % 2 == 1:
     # Horizontal
     range[1] = str(col_num + int(range[1]))

def split_cell(target_range):
    # rangeの列の文字列を取得
    column = re.search(r"[A-Z]+",target_range).group()
    # rangeの行の数字を取得
    row = target_range[re.search(r"[0-9]+", target_range).start():]
    # rangeの列の文字列から列番号を取得
    col = 0
    for i, val in enumerate(list(column)):
       col += pow(26, len(column) - i - 1) * (ord(val) - ord('A') + 1)
    return [row,col]

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("left_up_x", help="X軸始点", type=int)
    parser.add_argument("left_up_y", help="Y軸始点", type=int)
    parser.add_argument("right_down_x", help="X軸終点", type=int)
    parser.add_argument("right_down_y", help="Y軸終点", type=int)
    parser.add_argument("book_name", help="使用する既存のExcelファイル名", type=str)
    parser.add_argument("sheet_name", help="使用する既存のシート名", type=str)
    parser.add_argument("target_range", help="最初のセル", type=str)
    args = parser.parse_args()
    main(args)

▼ 実行

PS C:\Users\USER\Documents\python> python .\getEvidenceRepeatAutoZ.py 242 260 957 748 test.xlsx test B2
続行する場合はenterしてください。終了する場合はendを入力してください

対象画面を表示してクリックしてください

続行する場合はenterしてください。終了する場合はendを入力してください

対象画面を表示してクリックしてください

続行する場合はenterしてください。終了する場合はendを入力してください

対象画面を表示してクリックしてください

続行する場合はenterしてください。終了する場合はendを入力してください
end

▼ 結果

おわりに

テストを終了してこんなのあったらよかったな。みたいな感じで作ってみました。
次のプロジェクトで役に立つかはわかりません。
AI開発していないのでPythonに触れることはないと思ってたけど、Excelと相性がいいことがわかったのでPythonに興味が湧きました。

参考リンク

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4