看了很多UI自動化框架,無論是開源的還是自己造輪子的,都是失敗後截最後一張圖或幾張圖。隨然沒有問題。但我們能不能換種思想。我們能不能把截圖全轉成gif動圖,這樣定位問題更直觀呢。
來吧。看看怎麼實現吧。
先看看樓主的思路吧,如下:
每一個用例中的步驟我們都截圖,然後再保存至對應用例的文件夾中,在跑完用例後,將文件夾中的圖片轉成gif文件,再刪除其它靜態圖片。
思路有了,再看看怎麼實現吧。背景是我們用的pytest框架,基於unitest Fixture
一、解析用例名
這步主要是用於獲取用例名,用於後面新建對應的用例名文件夾
def get_testname(self): full_stack = inspect.stack() index = -1 for stack_frame in full_stack: print(stack_frame[1],stack_frame[3]) if 'test_' in stack_frame[3]: index = full_stack.index(stack_frame) break testname = full_stack[index][3] return testname
其中,這裏篩選出來的是以含有test_的用例。可根據需要自己修改。
二、截圖的保存
這裏的思路就是每一個用例根據用例名創建文件夾,然後再將截圖存入
def save_screenshot(self,screenshot_name): "Take a screenshot" self.screenshots_parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'screenshots')) if not os.path.exists(self.screenshots_parent_dir): os.makedirs(self.screenshots_parent_dir) self.logs_parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'log')) if not os.path.exists(self.logs_parent_dir): os.makedirs(self.logs_parent_dir) self.screenshot_dir = self.screenshots_parent_dir + os.sep + self.gettestname() if not os.path.exists(self.screenshot_dir): os.makedirs(self.screenshot_dir) if os.path.exists(self.screenshot_dir + os.sep + screenshot_name+'.png'): for i in range(1,100): if os.path.exists(self.screenshot_dir + os.sep +screenshot_name+'_'+str(i)+'.png'): continue else: os.rename(self.screenshot_dir + os.sep +screenshot_name+'.png',self.screenshot_dir + os.sep +screenshot_name+'_'+str(i)+'.png') break screenshot_name = self.screenshot_dir + os.sep + screenshot_name+'.png' self.driver.get_screenshot_as_file(screenshot_name)
三、寫裝飾器用於步驟的截圖
class Wrapit(): def _screenshot(func): def wrapper(self, *args, **kwargs): result = func(self, *args, **kwargs) screenshot_name = '%003d' % self.screenshot_counter + '_' + func.__name__ self.screenshot_counter += 1 self.save_screenshot(screenshot_name) return result return wrapper
爲了防止步驟一樣,導致文件名重疊,所以加了一個計數器
四、將裝飾器用於動作的封裝中
@Wrapit._screenshot def input_name(self, text): self.driver.find_element_by_id('kw').send_keys(text)
五、生成gif
這步需要用於Pillow庫
def make_gif(self, screenshot_dir_path, name = "test_png",suffix=".gif",duration=500): images = [] from PIL import Image filenames = os.listdir(screenshot_dir_path) gif_name = os.path.join(screenshot_dir_path, name + suffix) for files in sorted(filenames): im = Image.open(os.path.join(screenshot_dir_path, files)) images.append(im) images[0].save(gif_name, save_all=True, loop=True, append_images=images[1:], duration=duration)
六、刪除其它png文件
def clean_png(self, screenshot_dir_path): filenames = os.listdir(screenshot_dir_path) fileanames = [name for name in filenames if name.endswith('.png')] for files in sorted(fileanames): print('remove file %s' % files) os.remove(os.path.join(screenshot_dir_path, files))
7、將生成gif和刪除png動作放在teardown中
def tearDown(self) -> None: self.page.make_gif(self.page.screenshot_dir) self.clean_png(self.page.screenshot_dir)
完成後,會生成如果這樣的gif
我的用例步驟是:
1.打開百度
2.輸入xxxx
3.點擊百度一下
4.再點擊百度首頁
------可能問題-----
你可能會問到。如果使用的是類繼承,導致用例名是一樣的,怎麼處理?只需要修改獲取用例名的函數的方法
未放完整的代碼上去。如果有需要的朋友可以直接聯繫,一起探討。
還需要優化的地方:
點擊某個地方或者找某個元素,需要高亮一下。這樣讓定位更清晰