Skip to content

Commit

Permalink
Create auto test script (#676)
Browse files Browse the repository at this point in the history
* add retry
* auto test
* fix some bug


---------

Co-authored-by: Zirui Cai <[email protected]>
  • Loading branch information
SAKURA-CAT and Feudalman authored Aug 14, 2024
1 parent 62d15f9 commit a31da69
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 14 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/test-when-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Test When PR

on:
pull_request:
paths:
- swanlab/**
- test/**
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip' # 缓存 pip 依赖

- name: Install Dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-media.txt
pip install -r requirements-dev.txt
- name: Test
# 部分环境变量没有用到,不过后续可能会用到,所以先保留
run: |
export SWANLAB_RUNTIME=test-no-cloud
export SWANLAB_WEB_HOST=${{ secrets.SWANLAB_WEB_HOST }}
export SWANLAB_API_HOST=${{ secrets.SWANLAB_API_HOST }}
export SWANLAB_API_KEY=${{ secrets.SWANLAB_API_KEY }}
export PYTHONPATH=$PYTHONPATH:.
pytest test/unit
3 changes: 2 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ torchvision
python-dotenv
freezegun
build
requests-mock
responses
requests-mock==1.12.1 # 不太好用,即将删除
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
swankit==0.1.1b1
swanboard==0.1.3b5
cos-python-sdk-v5
urllib3
requests
click
pyyaml
Expand Down
12 changes: 12 additions & 0 deletions swanlab/api/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from swankit.log import FONT
from swanlab.log import swanlog
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import json


Expand Down Expand Up @@ -118,8 +120,18 @@ def __before_request(self):
def __create_session(self):
"""
创建会话,这将在HTTP类实例化时调用
添加了重试策略
"""
session = requests.Session()
retry = Retry(
total=3,
backoff_factor=0.1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=frozenset(["GET", "POST", "PUT", "DELETE", "PATCH"]),
)
adapter = HTTPAdapter(max_retries=retry)
session.mount("https://", adapter)

session.headers["swanlab-sdk"] = self.__version
session.cookies.update({"sid": self.__login_info.sid})

Expand Down
2 changes: 1 addition & 1 deletion swanlab/api/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def __str__(self) -> str:
return "Error api key"
if self.__resp.reason == "Forbidden":
return "You need to be verified first"
return self.__resp.reason
return str(self.__resp.status_code) + " " + self.__resp.reason

def save(self):
"""
Expand Down
File renamed without changes.
35 changes: 29 additions & 6 deletions test/unit/api/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
开发环境下存储凭证过期时间为3s
"""
import os
import time
import nanoid
from swanlab.api.http import create_http, HTTP, CosClient
from swanlab.api.auth.login import login_by_key
from swanlab.data.modules import MediaBuffer
from tutils import API_KEY, TEMP_PATH, is_skip_cloud_test
from tutils.setup import UseMocker, UseSetupHttp
import pytest
import responses
from responses import registries

alphabet = "abcdefghijklmnopqrstuvwxyz"

Expand All @@ -32,6 +33,26 @@ def test_decode_response():
assert data == "test"


@responses.activate(registry=registries.OrderedRegistry)
def test_retry():
"""
测试重试机制
"""
from swanlab.package import get_host_api
url = get_host_api() + "/retry"
rsp1 = responses.get(url, body="Error", status=500)
rsp2 = responses.get(url, body="Error", status=500)
rsp3 = responses.get(url, body="Error", status=500)
rsp4 = responses.get(url, body="OK", status=200)
with UseSetupHttp() as http:
data = http.get("/retry")
assert data == "OK"
assert rsp1.call_count == 1
assert rsp2.call_count == 1
assert rsp3.call_count == 1
assert rsp4.call_count == 1


@pytest.mark.skipif(is_skip_cloud_test, reason="skip cloud test")
class TestCosSuite:
http: HTTP = None
Expand Down Expand Up @@ -67,8 +88,10 @@ def test_cos_upload(self):
buffer.write(b"test")
buffer.file_name = "test"
self.http.upload(buffer)
# 开发版本设置的过期时间为3s,等待过期
time.sleep(3)
# 重新上传,测试刷新
assert self.http.cos.should_refresh is True
self.http.upload(buffer)
# 为了开发方便,测试刷新功能关闭

# # 开发版本设置的过期时间为3s,等待过期
# time.sleep(3)
# # 重新上传,测试刷新
# assert self.http.cos.should_refresh is True
# self.http.upload(buffer)
8 changes: 6 additions & 2 deletions test/unit/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,16 @@ def test_get_experiment_url():
# ---------------------------------- 登录部分 ----------------------------------

class TestGetKey:
@staticmethod
def remove_env_key():
if SwanLabEnv.API_KEY.value in os.environ:
del os.environ[SwanLabEnv.API_KEY.value]

def test_ok(self):
"""
获取key成功
"""
del os.environ[SwanLabEnv.API_KEY.value]
self.remove_env_key()
# 首先需要登录
file = os.path.join(get_save_dir(), ".netrc")
with open(file, "w"):
Expand All @@ -96,7 +100,7 @@ def test_no_file(self):
"""
文件不存在
"""
del os.environ[SwanLabEnv.API_KEY.value]
self.remove_env_key()
from swanlab.error import KeyFileError
with pytest.raises(KeyFileError) as e:
P.get_key()
Expand Down
9 changes: 5 additions & 4 deletions tutils/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ def mock_login_info(
m.post(f"{get_host_api()}/login/api_key", status_code=status_code, reason=error_reason)
else:
expired_at = datetime.now().isoformat()
expired_at = (datetime.fromisoformat(expired_at) + timedelta(days=7)).isoformat() + 'Z'
# 过期时间为当前时间加8天,主要是时区问题,所以不能7天以内
expired_at = (datetime.fromisoformat(expired_at) + timedelta(days=8)).isoformat() + 'Z'
m.post(f"{get_host_api()}/login/api_key", json={
"sid": nanoid.generate(),
# 时间为当前时间加7天
"expiredAt": expired_at,
"userInfo": {
"username": username
Expand All @@ -62,7 +62,7 @@ def mock_login_info(

class UseSetupHttp:
"""
用于全局使用的http对象
用于全局使用的http对象,模拟登录,退出时重置http
使用with关键字,自动登录,退出时自动重置http
也可以使用del手动释放
"""
Expand Down Expand Up @@ -93,8 +93,9 @@ class UseMocker(requests_mock.Mocker):
使用request_mock库进行mock测试,由于现在绝大部分请求都在get_host_api上,所以封装一层
"""

def __init__(self, base_url=get_host_api()):
def __init__(self, base_url: str = None):
super().__init__()
base_url = base_url or get_host_api()
self.base_url = base_url

def get(self, router, *args, **kwargs):
Expand Down

0 comments on commit a31da69

Please sign in to comment.