Tự động chụp lại screenshot khi scenario bị lỗi trên CircleCI
Hiện tại công ty của mình đang sử dụng Cucumber và Selenium để chạy các acceptance test. Mỗi khi có scenario nào fail trên CircleCI, thì bên mình sẽ chạy lại cái scenario đó dưới máy local để kiểm tra lại. Khoảng một tháng gần đây, sau khi áp dụng UI design mới thì gặp một vấn đề hết sức kì cục là: ...
Hiện tại công ty của mình đang sử dụng Cucumber và Selenium để chạy các acceptance test. Mỗi khi có scenario nào fail trên CircleCI, thì bên mình sẽ chạy lại cái scenario đó dưới máy local để kiểm tra lại. Khoảng một tháng gần đây, sau khi áp dụng UI design mới thì gặp một vấn đề hết sức kì cục là: scenario fail trên CircleCI nhưng khi chạy ở dưới máy local thì vẫn bình thường.
Để biết được cái gì gây ra lỗi này mình nghĩ cần có một bằng chứng xác thực, sau đó mới phán đoán thì sẽ chính xác hơn là đoán mò chỉ tổ tốn thêm thời gian (mình đã đoán mò khá nhiều nên biết cái này @@ ). Vì vậy chụp lại được screenshot của scenario ngay khi bị fail trên CircleCI, sau đó xem lại screenshot là một cách khá là ổn để debug lỗi.
Mình viết đoạn code sau vào After hooks để cho Cucumber tự động chụp lại và lưu lại screenshot khi có scenario nào bị fail.
# features/support/env.rb After do |scenario| if scenario.failed? timestamp = "#{Time.zone.now.strftime('%Y-%m-%d-%H:%M:%S')}" screenshot_name = "screenshot-#{scenario.title}-#{timestamp}.png" screenshot_path = "#{Rails.root.join('tmp/capybara')}/#{screenshot_name}" Capybara.page.save_screenshot(screenshot_path) end end
Bây giờ thì mỗi khi có scenario nào fail thì screenshot được lưu vô thư mục đã chỉ định, ở đây là tmp/capybara.
Nhưng hiện tại chỉ mới chụp và lưu được screenshot ở môi trường development. Cái mình cần là những screenshot được chụp và lưu lại ở CircleCI khi chạy trên đó. May mắn thay, CircleCI có cung cấp $CIRCLE_ARTIFACTS , một thư mục mà chúng ta có thể ghi file và sau đó xem được những file đó sau khi quá trình build hoàn tất.
Sửa lại đoạn code trên một chút như sau.
# features/support/env.rb After do |scenario| if scenario.failed? timestamp = "#{Time.zone.now.strftime('%Y-%m-%d-%H:%M:%S')}" screenshot_name = "screenshot-#{scenario.title}-#{timestamp}.png" screenshot_path = "#{ENV.fetch('CIRCLE_ARTIFACTS', Rails.root.join('tmp/capybara'))}/#{screenshot_name}" Capybara.page.save_screenshot(screenshot_path) end end
Biến ENV["CIRCLE_ARTIFACTS"] chứa giá trị là đường dẫn đến thư mục $CIRCLE_ARTIFACTS, CircleCI sẽ set giá trị cho nó khi build trên ấy, các bạn không cần phải set giá trị của biến này.
Mình sử dụng phương thức fetch (Hash) để khi giá trị ENV["CIRCLE_ARTIFACTS"] rỗng (khi chạy trên môi trường development) thì sẽ lấy đường dẫn là tmp/capybara.
Sau khi chụp được các screenshot trên CircleCI, các bạn có thể vào tab Artifacts để click xem các screenshot này.
Hy vọng, tip này có thể tiết kiệm kha khá thời gian debug của các bạn. Happy hacking!
P/s: Sau khi xem screenshot bên mình đã phát hiện ra được nguyên nhân gây ra lỗi test fail trên CircleCI nhưng vẫn pass khi chạy ở máy local. Hoá ra là trên CircleCI, kích cỡ của trình duyệt khác với kích cỡ của trình duyệt trên máy local. Vì design reponsive không kỹ, nên khi size nhỏ hơn bình thường làm các thẻ div đè lên nhau, Cucumber không thể chọn và click được element và văng ra lỗi. Phù.