From 9e73328448e71d57bb801b5817d7becbd2f5ed57 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Sun, 16 Apr 2023 22:11:35 +0800 Subject: [PATCH] refactor: TakeScreenShot saves all screenshots --- examples/worldcup/main.go | 6 +--- hrp/cmd/adb/screencap.go | 5 ++-- hrp/internal/builtin/utils.go | 4 +++ hrp/pkg/gadb/device.go | 4 ++- hrp/pkg/uixt/ext.go | 53 ++++++++++++++++++----------------- hrp/pkg/uixt/interface.go | 12 -------- hrp/pkg/uixt/ocr_vedem.go | 17 ++--------- hrp/pkg/uixt/opencv.go | 6 ++-- hrp/step_mobile_ui.go | 15 ++++------ 9 files changed, 50 insertions(+), 72 deletions(-) diff --git a/examples/worldcup/main.go b/examples/worldcup/main.go index e67f024c..697bcd57 100644 --- a/examples/worldcup/main.go +++ b/examples/worldcup/main.go @@ -150,11 +150,7 @@ func NewWorldCupLive(device uixt.Device, matchName, bundleID string, duration, i func (wc *WorldCupLive) getCurrentLiveTime(utcTime time.Time) error { utcTimeStr := utcTime.Format("15:04:05") - fileName := filepath.Join( - wc.resultDir, "screenshot", utcTimeStr) - ocrTexts, err := wc.driver.GetTextsByOCR( - uixt.WithScreenShot(fileName), - ) + ocrTexts, err := wc.driver.GetTextsByOCR() if err != nil { log.Error().Err(err).Msg("get ocr texts failed") return err diff --git a/hrp/cmd/adb/screencap.go b/hrp/cmd/adb/screencap.go index d9166191..bb1ddf6c 100644 --- a/hrp/cmd/adb/screencap.go +++ b/hrp/cmd/adb/screencap.go @@ -3,9 +3,10 @@ package adb import ( "fmt" "io/ioutil" - "time" "github.com/spf13/cobra" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) var screencapAndroidDevicesCmd = &cobra.Command{ @@ -22,7 +23,7 @@ var screencapAndroidDevicesCmd = &cobra.Command{ return err } - filepath := fmt.Sprintf("screencap_%d.png", time.Now().Unix()) + filepath := fmt.Sprintf("%s.png", builtin.GenNameWithTimestamp("screencap_")) if err = ioutil.WriteFile(filepath, res, 0o644); err != nil { return err } diff --git a/hrp/internal/builtin/utils.go b/hrp/internal/builtin/utils.go index 63dbfd0f..a27ac366 100644 --- a/hrp/internal/builtin/utils.go +++ b/hrp/internal/builtin/utils.go @@ -443,3 +443,7 @@ func Sign(ver string, ak string, sk string, body []byte) string { signResult := sha256HMAC(signKey, body) return fmt.Sprintf("%v/%v", signKeyInfo, string(signResult)) } + +func GenNameWithTimestamp(prefix string) string { + return fmt.Sprintf("%s%d", prefix, time.Now().Unix()) +} diff --git a/hrp/pkg/gadb/device.go b/hrp/pkg/gadb/device.go index 181609b0..dfac9042 100644 --- a/hrp/pkg/gadb/device.go +++ b/hrp/pkg/gadb/device.go @@ -11,6 +11,8 @@ import ( "time" "github.com/rs/zerolog/log" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) type DeviceFileInfo struct { @@ -538,7 +540,7 @@ func (d *Device) InstallAPK(apk io.ReadSeeker) (string, error) { return string(raw), err } - remote := fmt.Sprintf("/data/local/tmp/gadb_remote_%d.apk", time.Now().Unix()) + remote := fmt.Sprintf("/data/local/tmp/%s.apk", builtin.GenNameWithTimestamp("gadb_remote_")) err := d.Push(apk, remote, time.Now()) if err != nil { return "", fmt.Errorf("error pushing: %v", err) diff --git a/hrp/pkg/uixt/ext.go b/hrp/pkg/uixt/ext.go index 093cb776..6b495370 100644 --- a/hrp/pkg/uixt/ext.go +++ b/hrp/pkg/uixt/ext.go @@ -217,7 +217,7 @@ type DriverExt struct { doneMjpegStream chan bool scale float64 ocrService OCRService // used to get text from image - ScreenShots []string // save screenshots path + screenShots []string // cache screenshot paths CVArgs } @@ -253,7 +253,9 @@ func NewDriverExt(device Device, driver WebDriver) (dExt *DriverExt, err error) return dExt, nil } -func (dExt *DriverExt) takeScreenShot() (raw *bytes.Buffer, err error) { +// TakeScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder +// if fileName is empty, it will not save image file and only return raw image data +func (dExt *DriverExt) TakeScreenShot(fileName ...string) (raw *bytes.Buffer, err error) { // wait for action done time.Sleep(500 * time.Millisecond) @@ -263,14 +265,27 @@ func (dExt *DriverExt) takeScreenShot() (raw *bytes.Buffer, err error) { return dExt.frame, nil } if raw, err = dExt.Driver.Screenshot(); err != nil { - log.Error().Err(err).Msg("takeScreenShot failed") + log.Error().Err(err).Msg("capture screenshot data failed") return nil, err } + + // save screenshot to file + if len(fileName) > 0 && fileName[0] != "" { + path := filepath.Join(env.ScreenShotsPath, fileName[0]) + path, err := dExt.saveScreenShot(raw, path) + if err != nil { + log.Error().Err(err).Msg("save screenshot file failed") + return nil, err + } + dExt.screenShots = append(dExt.screenShots, path) + log.Info().Str("path", path).Msg("save screenshot file success") + } + return raw, nil } // saveScreenShot saves image file with file name -func saveScreenShot(raw *bytes.Buffer, fileName string) (string, error) { +func (dExt *DriverExt) saveScreenShot(raw *bytes.Buffer, fileName string) (string, error) { img, format, err := image.Decode(raw) if err != nil { return "", errors.Wrap(err, "decode screenshot image failed") @@ -302,19 +317,11 @@ func saveScreenShot(raw *bytes.Buffer, fileName string) (string, error) { return screenshotPath, nil } -// ScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder -func (dExt *DriverExt) ScreenShot(fileName string) (string, error) { - raw, err := dExt.takeScreenShot() - if err != nil { - return "", errors.Wrap(err, "screenshot failed") - } - - fileName = filepath.Join(env.ScreenShotsPath, fileName) - path, err := saveScreenShot(raw, fileName) - if err != nil { - return "", errors.Wrap(err, "save screenshot failed") - } - return path, nil +func (dExt *DriverExt) GetScreenShots() []string { + defer func() { + dExt.screenShots = nil + }() + return dExt.screenShots } // isPathExists returns true if path exists, whether path is file or dir @@ -689,15 +696,9 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { } } case CtlScreenShot: - // take snapshot - log.Info().Msg("take snapshot for current screen") - screenshotPath, err := dExt.ScreenShot(fmt.Sprintf("screenshot_%d", - time.Now().Unix())) - if err != nil { - return errors.Wrap(err, "take screenshot failed") - } - log.Info().Str("path", screenshotPath).Msg("take screenshot") - dExt.ScreenShots = append(dExt.ScreenShots, screenshotPath) + // take screenshot + log.Info().Msg("take screenshot for current screen") + _, err := dExt.TakeScreenShot(builtin.GenNameWithTimestamp("screenshot_")) return err case CtlStartCamera: return dExt.Driver.StartCamera() diff --git a/hrp/pkg/uixt/interface.go b/hrp/pkg/uixt/interface.go index 501e6862..7d6145b3 100644 --- a/hrp/pkg/uixt/interface.go +++ b/hrp/pkg/uixt/interface.go @@ -2,7 +2,6 @@ package uixt import ( "bytes" - "fmt" "math" "strings" "time" @@ -437,7 +436,6 @@ type DataOptions struct { IgnoreNotFoundError bool // ignore error if target element not found MaxRetryTimes int // max retry times if target element not found Interval float64 // interval between retries in seconds - ScreenShotFilename string // turn on screenshot and specify file name } type DataOption func(data *DataOptions) @@ -514,16 +512,6 @@ func WithDataWaitTime(sec float64) DataOption { } } -func WithScreenShot(fileName ...string) DataOption { - return func(data *DataOptions) { - if len(fileName) > 0 { - data.ScreenShotFilename = fileName[0] - } else { - data.ScreenShotFilename = fmt.Sprintf("screenshot_%d", time.Now().Unix()) - } - } -} - func NewDataOptions(options ...DataOption) *DataOptions { dataOptions := &DataOptions{ Data: make(map[string]interface{}), diff --git a/hrp/pkg/uixt/ocr_vedem.go b/hrp/pkg/uixt/ocr_vedem.go index f68964b6..48bb804a 100644 --- a/hrp/pkg/uixt/ocr_vedem.go +++ b/hrp/pkg/uixt/ocr_vedem.go @@ -175,14 +175,6 @@ func (s *veDEMOCRService) GetTexts(imageBuf *bytes.Buffer, options ...DataOption dataOptions := NewDataOptions(options...) - if dataOptions.ScreenShotFilename != "" { - path, err := saveScreenShot(imageBuf, dataOptions.ScreenShotFilename) - if err != nil { - return nil, errors.Wrap(err, "save screenshot failed") - } - log.Debug().Str("path", path).Msg("save screenshot") - } - for _, ocrResult := range ocrResults { rect := image.Rectangle{ // ocrResult.Points 顺序:左上 -> 右上 -> 右下 -> 左下 @@ -313,8 +305,7 @@ type OCRService interface { func (dExt *DriverExt) GetTextsByOCR(options ...DataOption) (texts OCRTexts, err error) { var bufSource *bytes.Buffer - if bufSource, err = dExt.takeScreenShot(); err != nil { - err = fmt.Errorf("takeScreenShot error: %v", err) + if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("ocr_")); err != nil { return } @@ -329,8 +320,7 @@ func (dExt *DriverExt) GetTextsByOCR(options ...DataOption) (texts OCRTexts, err func (dExt *DriverExt) FindTextByOCR(ocrText string, options ...DataOption) (x, y, width, height float64, err error) { var bufSource *bytes.Buffer - if bufSource, err = dExt.takeScreenShot(); err != nil { - err = fmt.Errorf("takeScreenShot error: %v", err) + if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("ocr_")); err != nil { return } @@ -348,8 +338,7 @@ func (dExt *DriverExt) FindTextByOCR(ocrText string, options ...DataOption) (x, func (dExt *DriverExt) FindTextsByOCR(ocrTexts []string, options ...DataOption) (points [][]float64, err error) { var bufSource *bytes.Buffer - if bufSource, err = dExt.takeScreenShot(); err != nil { - err = fmt.Errorf("takeScreenShot error: %v", err) + if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("ocr_")); err != nil { return } diff --git a/hrp/pkg/uixt/opencv.go b/hrp/pkg/uixt/opencv.go index 6a5b3bb8..95e10783 100644 --- a/hrp/pkg/uixt/opencv.go +++ b/hrp/pkg/uixt/opencv.go @@ -14,6 +14,8 @@ import ( "github.com/pkg/errors" "gocv.io/x/gocv" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) const ( @@ -101,7 +103,7 @@ func (dExt *DriverExt) FindAllImageRect(search string) (rects []image.Rectangle, if bufSearch, err = getBufFromDisk(search); err != nil { return nil, err } - if bufSource, err = dExt.takeScreenShot(); err != nil { + if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("cv_")); err != nil { return nil, err } @@ -116,7 +118,7 @@ func (dExt *DriverExt) FindImageRectInUIKit(imagePath string, options ...DataOpt if bufSearch, err = getBufFromDisk(imagePath); err != nil { return 0, 0, 0, 0, err } - if bufSource, err = dExt.takeScreenShot(); err != nil { + if bufSource, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("cv_")); err != nil { return 0, 0, 0, 0, err } diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index f5483488..6cfb90d1 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -2,11 +2,11 @@ package hrp import ( "fmt" - "time" "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/code" "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) @@ -572,7 +572,6 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err Success: false, ContentSize: 0, } - screenshots := make([]string, 0) // merge step variables with session variables stepVariables, err := s.ParseStepVariables(step.Variables) @@ -602,18 +601,14 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err } // take screenshot after each step - screenshotPath, err := uiDriver.ScreenShot( - fmt.Sprintf("step_%d", time.Now().Unix())) + _, err := uiDriver.TakeScreenShot( + builtin.GenNameWithTimestamp("step_") + "_" + step.Name) if err != nil { - log.Error().Err(err).Str("step", step.Name).Msg("take screenshot failed") - } else { - log.Info().Str("path", screenshotPath).Msg("take screenshot on step finished") - screenshots = append(screenshots, screenshotPath) + log.Error().Err(err).Str("step", step.Name).Msg("take screenshot failed on step finished") } // save attachments - screenshots = append(screenshots, uiDriver.ScreenShots...) - attachments["screenshots"] = screenshots + attachments["screenshots"] = uiDriver.GetScreenShots() stepResult.Attachments = attachments }()