From 683bbdd7f6efd022709d6573b7a92f90fd8ce338 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 7 Mar 2025 11:38:50 +0800 Subject: [PATCH 1/7] test: add unittest for adb PushImage/ClearImages --- internal/version/VERSION | 2 +- uixt/android_driver_adb.go | 1 + uixt/android_test.go | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/version/VERSION b/internal/version/VERSION index a74704b2..cd45c15f 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503062216 +v5.0.0-beta-2503071138 diff --git a/uixt/android_driver_adb.go b/uixt/android_driver_adb.go index 22f63b54..e812852d 100644 --- a/uixt/android_driver_adb.go +++ b/uixt/android_driver_adb.go @@ -925,6 +925,7 @@ func (ad *ADBDriver) PushImage(localPath string) error { if err := ad.Device.PushFile(localPath, remotePath); err != nil { return err } + // refresh _, _ = ad.Device.RunShellCommand("am", "broadcast", "-a", "android.intent.action.MEDIA_SCANNER_SCAN_FILE", "-d", fmt.Sprintf("file://%s", remotePath)) diff --git a/uixt/android_test.go b/uixt/android_test.go index c18c67e0..13620e1f 100644 --- a/uixt/android_test.go +++ b/uixt/android_test.go @@ -244,6 +244,22 @@ func TestDriver_ADB_ScreenRecord(t *testing.T) { assert.Nil(t, err) } +func TestDriver_ADB_PushImage(t *testing.T) { + driver := setupADBDriverExt(t) + + screenshot, err := driver.ScreenShot() + assert.Nil(t, err) + path, err := saveScreenShot(screenshot, "1234") + require.Nil(t, err) + defer os.Remove(path) + + err = driver.PushImage(path) + assert.Nil(t, err) + + err = driver.ClearImages() + assert.Nil(t, err) +} + func TestDriver_ADB_Backspace(t *testing.T) { driver := setupADBDriverExt(t) err := driver.Backspace(1) From ae4e8b3dd1fab775979fd1c91a125e863f608df0 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 7 Mar 2025 12:00:46 +0800 Subject: [PATCH 2/7] change: downgrade to go 1.22 --- go.mod | 2 +- internal/version/VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index eab5717b..1cd1c35c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/httprunner/httprunner/v5 -go 1.23.0 +go 1.22.0 require ( github.com/Masterminds/semver v1.5.0 diff --git a/internal/version/VERSION b/internal/version/VERSION index cd45c15f..38ad85e6 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503071138 +v5.0.0-beta-2503071200 From 80b18f6d053f380fe408ec36e6169c7e1dc1e7bb Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 7 Mar 2025 12:09:08 +0800 Subject: [PATCH 3/7] test: add unittest for WDA PushImage/ClearImages --- internal/version/VERSION | 2 +- uixt/ios_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/version/VERSION b/internal/version/VERSION index 38ad85e6..099f926a 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503071200 +v5.0.0-beta-2503071209 diff --git a/uixt/ios_test.go b/uixt/ios_test.go index 6fe37bfd..ca89139b 100644 --- a/uixt/ios_test.go +++ b/uixt/ios_test.go @@ -312,3 +312,19 @@ func TestDriver_WDA_Backspace(t *testing.T) { err := driver.Backspace(3) assert.Nil(t, err) } + +func TestDriver_WDA_PushImage(t *testing.T) { + driver := setupWDADriverExt(t) + + screenshot, err := driver.ScreenShot() + assert.Nil(t, err) + path, err := saveScreenShot(screenshot, "1234") + require.Nil(t, err) + defer os.Remove(path) + + err = driver.PushImage(path) + assert.Nil(t, err) + + err = driver.ClearImages() + assert.Nil(t, err) +} From 7a00f5ff443327f56604054802eebf713a1902be Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 7 Mar 2025 23:08:46 +0800 Subject: [PATCH 4/7] feat: ios unmount --- cmd/ios/mount.go | 28 +++++++++++++++++----------- internal/version/VERSION | 2 +- uixt/ios_device.go | 24 +++++++++++++++++------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/cmd/ios/mount.go b/cmd/ios/mount.go index b48268dc..e51fd235 100644 --- a/cmd/ios/mount.go +++ b/cmd/ios/mount.go @@ -2,13 +2,14 @@ package ios import ( "fmt" + "os" + "path" "strings" "time" "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/sdk" ) @@ -31,6 +32,14 @@ var mountCmd = &cobra.Command{ return err } + if unmountDeveloperDiskImage { + err := device.UnmountImage() + if err != nil { + return fmt.Errorf("unmount developer disk image failed: %v", err) + } + return nil + } + images, errImage := device.ListImages() if err != nil { return fmt.Errorf("list device images failed: %v", err) @@ -47,12 +56,6 @@ var mountCmd = &cobra.Command{ return nil } - log.Info().Str("dir", developerDiskImageDir).Msg("start to mount ios developer image") - - if !builtin.IsFolderPathExists(developerDiskImageDir) { - return fmt.Errorf("developer disk image directory not exist: %s", developerDiskImageDir) - } - if err = device.AutoMountImage(developerDiskImageDir); err != nil { return fmt.Errorf("mount developer disk image failed: %s", err) } @@ -62,15 +65,18 @@ var mountCmd = &cobra.Command{ }, } -const defaultDeveloperDiskImageDir = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/" - var ( - developerDiskImageDir string - listDeveloperDiskImage bool + developerDiskImageDir string + listDeveloperDiskImage bool + unmountDeveloperDiskImage bool ) func init() { + home, _ := os.UserHomeDir() + defaultDeveloperDiskImageDir := path.Join(home, ".devimages") + mountCmd.Flags().BoolVar(&listDeveloperDiskImage, "list", false, "list developer disk images") + mountCmd.Flags().BoolVar(&unmountDeveloperDiskImage, "reset", false, "unmount developer disk images") mountCmd.Flags().StringVarP(&developerDiskImageDir, "dir", "d", defaultDeveloperDiskImageDir, "specify developer disk image directory") mountCmd.Flags().StringVarP(&udid, "udid", "u", "", "specify device by udid") iosRootCmd.AddCommand(mountCmd) diff --git a/internal/version/VERSION b/internal/version/VERSION index 099f926a..25200320 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503071209 +v5.0.0-beta-2503072308 diff --git a/uixt/ios_device.go b/uixt/ios_device.go index 79d3131e..8aae0d9f 100644 --- a/uixt/ios_device.go +++ b/uixt/ios_device.go @@ -24,6 +24,7 @@ import ( "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v5/code" + "github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/uixt/option" "github.com/httprunner/httprunner/v5/uixt/types" ) @@ -387,13 +388,7 @@ func (dev *IOSDevice) ListImages() (images []string, err error) { func (dev *IOSDevice) MountImage(imagePath string) (err error) { log.Info().Str("imagePath", imagePath).Msg("mount ios developer image") - conn, err := imagemounter.NewImageMounter(dev.DeviceEntry) - if err != nil { - return errors.Wrap(code.DeviceConnectionError, err.Error()) - } - defer conn.Close() - - err = conn.MountImage(imagePath) + err = imagemounter.MountImage(dev.DeviceEntry, imagePath) if err != nil { return errors.Wrapf(code.DeviceConnectionError, "mount ios developer image failed: %v", err) @@ -402,8 +397,23 @@ func (dev *IOSDevice) MountImage(imagePath string) (err error) { return nil } +func (dev *IOSDevice) UnmountImage() (err error) { + log.Info().Msg("unmount ios developer image") + err = imagemounter.UnmountImage(dev.DeviceEntry) + if err != nil { + return errors.Wrapf(code.DeviceConnectionError, + "unmount ios developer image failed: %v", err) + } + log.Info().Msg("unmount ios developer image success") + return nil +} + func (dev *IOSDevice) AutoMountImage(baseDir string) (err error) { log.Info().Str("baseDir", baseDir).Msg("auto mount ios developer image") + if err := builtin.EnsureFolderExists(baseDir); err != nil { + return errors.Wrap(err, "create developer disk image directory failed") + } + imagePath, err := imagemounter.DownloadImageFor(dev.DeviceEntry, baseDir) if err != nil { return errors.Wrapf(code.DeviceConnectionError, From 3b5b7281390820f05c43ada75a7ff3ec7dca65d1 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Fri, 7 Mar 2025 23:13:08 +0800 Subject: [PATCH 5/7] fix: hrp path --- .github/workflows/hrp-release.yml | 2 +- internal/version/VERSION | 2 +- scripts/build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/hrp-release.yml b/.github/workflows/hrp-release.yml index 4014daf5..4b3fbf8f 100644 --- a/.github/workflows/hrp-release.yml +++ b/.github/workflows/hrp-release.yml @@ -28,7 +28,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} goos: ${{ matrix.goos }} goarch: ${{ matrix.goarch }} - project_path: "hrp/cmd/cli/" # go build hrp/cmd/cli/main.go + project_path: "cmd/cli/" # go build cmd/cli/main.go binary_name: "hrp" ldflags: "-s -w" extra_files: LICENSE README.md docs/CHANGELOG.md diff --git a/internal/version/VERSION b/internal/version/VERSION index 25200320..16b60905 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503072308 +v5.0.0-beta-2503072313 diff --git a/scripts/build.sh b/scripts/build.sh index 855c0b0f..ccb2a30e 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -15,7 +15,7 @@ mkdir -p "output" bin_path="output/hrp" # build -go build -ldflags '-s -w' -o "$bin_path" hrp/cmd/cli/main.go +go build -ldflags '-s -w' -o "$bin_path" cmd/cli/main.go # check output and version ls -lh "$bin_path" From 69cb417e94ecf2b2aeb2a9c4dc64b9ef9bbd9a90 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Sat, 8 Mar 2025 00:14:30 +0800 Subject: [PATCH 6/7] change: introduction for httprunner --- README.en.md | 32 +++++++++++++++++++++++++------- README.md | 32 +++++++++++++++++++++++++------- cmd/root.go | 32 +++++++++++++++++++++++++------- internal/version/VERSION | 2 +- 4 files changed, 76 insertions(+), 22 deletions(-) diff --git a/README.en.md b/README.en.md index ab47eeec..c8dc2376 100644 --- a/README.en.md +++ b/README.en.md @@ -74,14 +74,32 @@ $ hrp -h ██║ ██║ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║██║ ╚████║███████╗██║ ██║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ -HttpRunner is an open source API testing tool that supports HTTP(S)/HTTP2/WebSocket/RPC -network protocols, covering API testing, performance testing and digital experience -monitoring (DEM) test types. Enjoy! ✨ 🚀 ✨ +HttpRunner: Enjoy your All-in-One Testing Solution ✨ 🚀 ✨ -License: Apache-2.0 +💡 Simple Yet Powerful + - Natural language driven test scenarios powered by LLM + - User-friendly SDK API with IDE auto-completion + - Intuitive GoTest/YAML/JSON/Text testcase format + +📌 Comprehensive Testing Capabilities + - UI Automation: Android/iOS/Harmony/Browser + - API Testing: HTTP(S)/HTTP2/WebSocket/RPC + - Load Testing: run API testcase concurrently with boomer + +🧩 High Scalability + - Plugin system for custom functions + - Distributed testing support + - Cross-platform: macOS/Linux/Windows + +🛠 Easy Integration + - CI/CD friendly with JSON logs and HTML reports + - Rich ecosystem tools + +Learn more: Website: https://httprunner.com -Github: https://github.com/httprunner/httprunner -Copyright 2017 debugtalk +GitHub: https://github.com/httprunner/httprunner + +Copyright © 2017-present debugtalk. Apache-2.0 License. Usage: hrp [command] @@ -101,7 +119,7 @@ Available Commands: Flags: -h, --help help for hrp - --log-json set log to json format + --log-json set log to json format (default colorized console) -l, --log-level string set log level (default "INFO") --venv string specify python3 venv path -v, --version version for hrp diff --git a/README.md b/README.md index cde11d17..c354d339 100644 --- a/README.md +++ b/README.md @@ -65,14 +65,32 @@ $ hrp -h ██║ ██║ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║██║ ╚████║███████╗██║ ██║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ -HttpRunner is an open source API testing tool that supports HTTP(S)/HTTP2/WebSocket/RPC -network protocols, covering API testing, performance testing and digital experience -monitoring (DEM) test types. Enjoy! ✨ 🚀 ✨ +HttpRunner: Enjoy your All-in-One Testing Solution ✨ 🚀 ✨ -License: Apache-2.0 +💡 Simple Yet Powerful + - Natural language driven test scenarios powered by LLM + - User-friendly SDK API with IDE auto-completion + - Intuitive GoTest/YAML/JSON/Text testcase format + +📌 Comprehensive Testing Capabilities + - UI Automation: Android/iOS/Harmony/Browser + - API Testing: HTTP(S)/HTTP2/WebSocket/RPC + - Load Testing: run API testcase concurrently with boomer + +🧩 High Scalability + - Plugin system for custom functions + - Distributed testing support + - Cross-platform: macOS/Linux/Windows + +🛠 Easy Integration + - CI/CD friendly with JSON logs and HTML reports + - Rich ecosystem tools + +Learn more: Website: https://httprunner.com -Github: https://github.com/httprunner/httprunner -Copyright 2017 debugtalk +GitHub: https://github.com/httprunner/httprunner + +Copyright © 2017-present debugtalk. Apache-2.0 License. Usage: hrp [command] @@ -92,7 +110,7 @@ Available Commands: Flags: -h, --help help for hrp - --log-json set log to json format + --log-json set log to json format (default colorized console) -l, --log-level string set log level (default "INFO") --venv string specify python3 venv path -v, --version version for hrp diff --git a/cmd/root.go b/cmd/root.go index 44d54e88..aed93bd3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -13,7 +13,7 @@ import ( // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "hrp", - Short: "Next-Generation API Testing Solution.", + Short: "All-in-One Testing Framework for API, UI and Performance", Long: ` ██╗ ██╗████████╗████████╗██████╗ ██████╗ ██╗ ██╗███╗ ██╗███╗ ██╗███████╗██████╗ ██║ ██║╚══██╔══╝╚══██╔══╝██╔══██╗██╔══██╗██║ ██║████╗ ██║████╗ ██║██╔════╝██╔══██╗ @@ -22,14 +22,32 @@ var rootCmd = &cobra.Command{ ██║ ██║ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║██║ ╚████║███████╗██║ ██║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ -HttpRunner is an open source API testing tool that supports HTTP(S)/HTTP2/WebSocket/RPC -network protocols, covering API testing, performance testing and digital experience -monitoring (DEM) test types. Enjoy! ✨ 🚀 ✨ +HttpRunner: Enjoy your All-in-One Testing Solution ✨ 🚀 ✨ -License: Apache-2.0 +💡 Simple Yet Powerful + - Natural language driven test scenarios powered by LLM + - User-friendly SDK API with IDE auto-completion + - Intuitive GoTest/YAML/JSON/Text testcase format + +📌 Comprehensive Testing Capabilities + - UI Automation: Android/iOS/Harmony/Browser + - API Testing: HTTP(S)/HTTP2/WebSocket/RPC + - Load Testing: run API testcase concurrently with boomer + +🧩 High Scalability + - Plugin system for custom functions + - Distributed testing support + - Cross-platform: macOS/Linux/Windows + +🛠 Easy Integration + - CI/CD friendly with JSON logs and HTML reports + - Rich ecosystem tools + +Learn more: Website: https://httprunner.com -Github: https://github.com/httprunner/httprunner -Copyright 2017 debugtalk`, +GitHub: https://github.com/httprunner/httprunner + +Copyright © 2017-present debugtalk. Apache-2.0 License.`, PersistentPreRun: func(cmd *cobra.Command, args []string) { hrp.InitLogger(logLevel, logJSON) }, diff --git a/internal/version/VERSION b/internal/version/VERSION index 16b60905..afdb1e4e 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503072313 +v5.0.0-beta-2503080014 From ef12ed3503443fbb9f0899ab4178002bee250d24 Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Sat, 8 Mar 2025 00:31:46 +0800 Subject: [PATCH 7/7] fix: install from github release --- internal/version/VERSION | 2 +- scripts/install.sh | 29 +++++++++-------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/internal/version/VERSION b/internal/version/VERSION index afdb1e4e..aaa993f9 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503080014 +v5.0.0-beta-2503080031 diff --git a/scripts/install.sh b/scripts/install.sh index 709167ff..9fc5a8a9 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -19,8 +19,12 @@ function echoWarn() { } export -f echoError +github_api_url="https://api.github.com/repos/httprunner/httprunner/releases/latest" + function get_latest_version() { - curl -ksSL https://httprunner.oss-cn-beijing.aliyuncs.com/VERSION + # get latest release version from GitHub API + version=$(curl -s $github_api_url | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + echo "$version" } function get_os() { @@ -59,28 +63,13 @@ function main() { pkg="hrp-$version-$os-$arch$pkg_suffix" echo "Download package: $pkg" - # download from aliyun OSS or github packages - aliyun_oss_url="https://httprunner.oss-cn-beijing.aliyuncs.com/$pkg" - github_url="https://github.com/httprunner/httprunner/releases/download/$version/$pkg" - valid_flag=false - for url in "$aliyun_oss_url" "$github_url"; do - if curl --output /dev/null --silent --head --fail "$url"; then - valid_flag=true - break - fi - echoWarn "Invalid download url: $url" - done - - if [[ "$valid_flag" == false ]]; then - echoError "No available download url found, exit!" - exit 1 - fi - echo "Download url: $url" + download_url=$(curl -s $github_api_url | grep "browser_download_url.*$pkg" | cut -d '"' -f 4) + echo "Download url: $download_url" echo echoInfo "Downloading..." - echo "$ curl -kL $url -o $pkg" - curl -kL $url -o "$pkg" + echo "$ curl -kL $download_url -o $pkg" + curl -kL $download_url -o "$pkg" echo # for windows, only extract package to current directory