扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

Ubuntu:算法自动化测试平台搭建

01/18 08:55
904
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

算法测试平台是专为验证、评估和优化算法设计的综合性工具或系统,广泛应用于机器学习、数据分析、人工智能等领域。其核心目标在于提升算法开发效率、确保结果可靠性,并支持团队协作,本文将搭建简易的算法平台,提供简单的实现方式(与实际项目有很大的不同),但实现思路是清晰的。

一、基本环境搭建

1、环境配置

以下配置适用于团队协作、持续集成(CI/CD)和中等并发测试任务(如数百个测试用例),能够满足在 Ubuntu 上搭建基于 ​Django + Docker + MySQL​ 的算法自动化测试平台。

Ubuntu版本:20.04

配置信息:8核CPU、16G内存、100G系统盘、500G硬盘

2、NFS系统搭建

NFS(Network File System,网络文件系统)​​ 是一种分布式文件系统协议,允许客户端通过网络访问远程服务器上的文件和目录,就像访问本地存储一样。它在 Unix/Linux 系统中广泛应用,尤其在分布式计算、集群管理和跨平台文件共享中扮演重要角色。

搭建文档:Ubuntu搭建nfs网络文件系统_ubuntu 网络文件系统-CSDN博客

挂载时需要注意:

服务器未启用 NFSv4协议,改用默认版本:

mount -t nfs IP地址:/data /root/test

启用时(一般为启用) ,使用NFSv4协议:

mount -t nfs4 IP地址:/data /root/test

而不指定版本直接输入以下指令,则nfs协议版本除了取决于服务器版本,还取决于mount的客户端版本,即可能是nfs4也可能是nfs,设置对于一些mount版本,即使强制指定nfs,实际挂载后也会是nfs4:

mount IP地址:/data /root/test

总之,客户端版本指定的nfs协议要与服务端一致才能正常连接,否则报错:mount: mounting **:/data on /root/test failed: Connection refused 。

查看已挂载的nfs版本:

mount | grep "/root/test"

卸载已挂载的磁盘:

umount 挂载的目录

3、python3环境(3.13.2

一般默认安装python3:

一般不装pip:

根据提示安装:

apt install python3-pip

最后发现pip与pip3都指向同一版本路径:

root@localhost:/# pip -V pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8) root@localhost:/# pip3 -V pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8) root@localhost:/#

这个不用管,pippip3指向同一程序是 Ubuntu 的默认行为(优先支持 Python 3),后面统一用pip3执行包的安装。

这里我们需要处理一下,安装高一级的python版本,需要安装conda来管理,本文使用python 3.13.2

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.shbash Miniconda3-latest-Linux-x86_64.shsource ~/miniconda3/bin/activate  # 进入默认的激活环境conda --version  # 查看 Conda 版本python --version  # 查看 Python 版本(默认安装的是 Python 3.12+)mkdir -p /data/pythons/3.13.2  # 创建3.13.2虚拟环境文件夹conda create --prefix "/data/pythons/3.13.2/env" python==3.13.2 -c conda-forge  # 创建3.13.2虚拟环境conda activate /data/pythons/3.13.2/env  # 激活/切换环境

4、ssh服务器

搭建文档:Ubuntu能够ping通,但不能ssh登录_能ping通ubuntu无法ssh登录-CSDN博客

5、远程开发环境(可选且推荐)

通过ssh实现,要求Ubuntu上启用ssh服务,如果用pycharm作为开发工具,则要求为专业版才能安装插件。操作步骤:

打开 PyCharm → ​File → Settings → Project: <项目名> → Python Interpreter

点击齿轮图标 → ​Add New Interpreter​ → ​SSH Interpreter(需要专业版且安装了插件才显示)。

输入 Ubuntu 的 IP 地址、用户名、密码(或 SSH 密钥)。

路径选择 Ubuntu 上的 Python 可执行文件(如/usr/bin/python3)等。

6、社区开发环境(可选且本文选择)

使用社区版pycharm作为开发工具,只是没有专业版方便,且可能在一些方面不好用,环境搭建可通过以下文档体验。

搭建文档:Django与MySQL实战-CSDN博客

7、git仓库

通过git创建工程,并通过pycharm加载工程。

搭建文档:Pycharm:通过git拉取仓库代码并创建项目环境_pycharm怎么拉取代码-CSDN博客

Ubuntu一般默认安装git,也可通过以下方式安装与配置:

sudo apt updatesudo apt install git  # 若已安装,可省略git --versiongit config --global user.name "你的姓名"git config --global user.email "你的邮箱@example.com"git config --listgit initgit clone "仓库地址"git clone "分支"

8、配置conda环境

使用Ancinda3来管理虚拟环境,配置与Ubuntu同版本python,即3.13.2。

搭建文档:Anconda3 的使用_anaconda3-CSDN博客

在pycharm中使用conda环境:

9、django 5.1.3

按照以下步骤创建工程并上传代码到git上。

Ubuntu安装django 5.1.3

conda install django==5.1.3 --channel conda-forge

10、Ubuntu运行服务

在settings文件中设置

ALLOWED_HOSTS = ["服务器本地IP地址"]

运行时使用conda指定的环境运行

python manage.py runserver 0.0.0.0:8000

在电脑上能访问Ubuntu服务即可

11、手动安装mysql 服务(可选,不推荐)

可直接用指令安装,在这里手动自定义安装:

wget https://dev.mysql.com/get/mysql-8.0.33-linux-glibc2.12-x86_64.tar.xzmkdir -p /data/mysqltar -xJvf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz -C /data/mysqlcd /data/mysqlsudo useradd -r -s /bin/false mysqlsudo ln -s /data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/share/english /data/mysql/sharemysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --initialize --user=mysql --basedir=/data/mysql --datadir=/data/mysql/data/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysql_ssl_rsa_setup --datadir=/data/mysql/datasudo nano /etc/profile.d/mysql.sh# 添加以下内容:export PATH=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin:$PATHexport LD_LIBRARY_PATH=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/lib:$LD_LIBRARY_PATHsource /etc/profile.d/mysql.shsudo nano /etc/systemd/system/mysql.service# 添加以下内容:[Unit]Description=MySQL Community ServerAfter=network.target[Service]User=mysqlGroup=mysqlExecStart=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --defaults-file=/etc/my.cnfExecStop=/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld_safe --shutdown[Install]WantedBy=multi-user.targetsudo nano /etc/my.cnf# 添加以下内容:[mysqld]datadir=/data/mysql/data# socket=/var/run/mysqld/mysqld.socksocket = ''bind-address = 0.0.0.0pid-file=/var/run/mysqld/mysqld.piduser=mysqlsymbolic-links=0[mysqld_safe]log-error=/var/log/mysqld.logpid-file=/var/run/mysqld/mysqld.pid[client]socket=/var/run/mysqld/mysqld.socksudo mkdir -p /var/run/mysqld sudo chown mysql:mysql /var/run/mysqldsudo chmod 750 /var/run/mysqld# 重新加载 systemd 配置sudo systemctl daemon-reload# 启动并启用服务sudo systemctl start mysqlsudo systemctl enable mysqlsudo systemctl status mysql

设置root无密码登录服务

sudo apt-get updatesudo apt-get install libtinfo5ldconfig -p | grep libtinfosudo systemctl stop mysqlsudo /data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysqld --skip-grant-tables --user=root &/data/mysql/mysql-8.0.33-linux-glibc2.12-x86_64/bin/mysql -u rootFLUSH PRIVILEGES;

创建数据库新用户newuser,mysql密码登录

CREATE USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;ALTER USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%' WITH GRANT OPTION;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost' WITH GRANT OPTION;FLUSH PRIVILEGES;exit;# 恢复环境ps aux | grep mysql  # 查找并杀掉所有进程,再重启服务

创建数据库

CREATE DATABASE algo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

配置django,首先安装mysqlclient,接着打开settings文件进行配置:

DATABASES = {    "default": {        "ENGINE": "django.db.backends.mysql",  # 使用 MySQL        "NAME": "algo_db",               # 数据库名        "USER": "newuser",              # 数据库用户名        "PASSWORD": "newpassword",          # 数据库密码        "HOST": "localhost",                  # MySQL 服务器地址        "PORT": "3306",                        # MySQL 端口号        "OPTIONS": {            "charset": "utf8mb4",             # 兼容 Emoji        },    }}

注意,我们要连接的是默认端口3306,而不是支持新协议的33060 (该端口支持MySQL X Protocol新协议):

12、安装docker

安装:

# 卸载旧版本sudo apt-get remove docker     docker-engine     docker.io     containerd.io# 安装必要工具sudo apt-get updatesudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release# 添加官方密钥curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 设置docker存储库echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -sc) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 安装 Docker CE(社区版)​sudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io# 验证sudo docker run hello-world# 输出 "Hello from Docker!" 表示安装成功# 安装 Docker Composesudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-composesudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose# 配置非rootsudo usermod -aG docker $USERnewgrp  # 使配置立即生效# 开机自启sudo systemctl enable dockersudo systemctl start docker

配置:

sudo mkdir -p /data/docker_appssudo chown -R 999:999 /data/docker_apps   # Docker 默认用户和组sudo chmod -R 755 /data/docker_appssudo systemctl stop docker# 移动原有数据到新目录sudo rsync -av /var/lib/docker/ /data/docker_apps/# 编辑 /etc/docker/daemon.json{  "data-root": "/data/docker_apps"}# 重启sudo systemctl start dockersudo systemctl enable docker# 验证# 查看 Docker 数据根目录sudo docker info | grep "Docker Root Dir"

13、使用docker安装mysql服务 (推荐)

sudo mkdir -p /data/docker_apps/mysql/{conf,sock,data}sudo chown -R 999:999 /data/docker_apps/mysql/  # Docker 用户和组sudo chmod -R 755 /data/docker_apps/mysql/cd /data/docker_apps/mysql# 创建文件docker-compose.yml,写入version: '3'services:  mysql:    image: mysql:8.0    container_name: test_mysql    volumes:      - /data/docker_apps/mysql/data:/var/lib/mysql    environment:      MYSQL_ROOT_PASSWORD: newpassword    ports:      - "3306:3306"# 启动sudo docker-compose up -d# 使用root登录sudo docker exec -it test_mysql mysql -uroot -pnewpasswordCREATE DATABASE IF NOT EXISTS algo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE USER 'newuser'@'%' IDENTIFIED BY 'newpassword';CREATE USER 'newuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;CREATE USER 'newuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'newpassword';FLUSH PRIVILEGES;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'%' WITH GRANT OPTION;GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost' WITH GRANT OPTION;FLUSH PRIVILEGES;

14、django mydql库的选择

优先选择mysqlclient,这也是官方推荐,备选pymysql 。

特性 PyMySQL mysqlclient (MySQLdb)
实现方式 纯 Python 实现 C 语言实现
安装难度 依赖少,pip install pymysql 即可 依赖 MySQL 开发库,安装可能较复杂
性能 稍慢(因纯 Python 实现) 更快(因 C 语言实现)
兼容性 兼容 MySQL 8.0(支持 caching_sha2_password 旧版本可能不支持 MySQL 8.0 认证方式
Python 版本支持 Python 3.x 主要支持 Python 3.x
维护情况 仍在积极维护 维护较少,较老的 MySQLdb 的封装
使用方式 兼容 MySQLdb API,可替代 mysqlclient 传统 MySQLdb 接口
django使用方式 # 强制使用,需要在setting文件中显示调用,配置与mysqlclient 一致。

import pymysqlpymysql.install_as_MySQLdb()
默认使用,安装即可

mysqlclient安装比较麻烦,在Ubuntu上安装不完整,通常会报以下错误:

django.db.utils.OperationalError: (2059, "Authentication plugin 'mysql_native_password' cannot be loaded: /data/pythons/3.13.2/env/lib/plugin/mysql_native_password.so: cannot open shared object file: No such file or directory") 在Ubuntu上安装mysqlclient时,务必按照官方文档进行安装:mysqlclient · PyPI

安装GUI

SSHFS-Win-Manager :Release v1.3.1 · evsar3/sshfs-win-manager (github.com)

挂载服务器成功:

15、SSHFS

winfsp/sshfs-win: SSHFS For Windows (github.com)

二、设计思路参考

1、需要具备的知识

django开发系列文章:Django让web开发更简单(一):运行MVT设计模式_note that only django core commands are listed as -CSDN博客

html学习:

HTML 简介 | 菜鸟教程 (runoob.com)

CSS学习:

CSS 教程 | 菜鸟教程 (runoob.com)

django模板(不推荐但本文使用):

Django 模板 | 菜鸟教程 (runoob.com)

如果前端用的VUE(推荐,但本文不使用),需要学习系列文章:

Vue 3:玩一下web前端技术(一)_web vue3-CSDN博客

本文会给个开发思路,但不深入技术细节与具体实现。

2、网页布局

base.html

{% load static %}<html lang="zh-CN"><head>    <meta charset="UTF-8">    <title>定制布局</title>    <style>        * { margin: 0; padding: 0; box-sizing: border-box }        .container {            display: grid;            grid-template-columns: 20% 80%;            min-height: 100vh;        }        .sidebar {            background-color: #333;            color: white;            padding: 15px;        }        .right-section {            display: grid;            grid-template-rows: 10% 90%;            height: 100%;        }        .header-bar {            background-color: #4CAF50;            color: white;            padding: 10px;            text-align: center;        }        .content-area {            padding: 20px;            background-color: #f5f5f5;        }    </style></head><body>    <div >        <!-- 左侧菜单栏 -->        <div >            <h3>导航菜单</h3>            <ul>                <li><a href="#">首页</a></li>                <li><a href="#">关于我们</a></li>                <li><a href="#">服务</a></li>                <li><a href="#">联系</a></li>            </ul>        </div>        <!-- 右侧内容区 -->        <div >            <!-- 顶部信息栏 -->            <div >                当前用户:{{ user.username }}                <span >2025-03-07 18:22:28</span>            </div>            <!-- 主要内容区域 -->            <div >                {% block content %}                    <p>这里是主要内容区域...</p>                {% endblock %}            </div>        </div>    </div></body></html>

index.html

{% extends "base.html" %}{% block title %}首页 - Algorithm Testing Platform{% endblock %}{% block content %}    <h1>欢迎来到算法测试平台!</h1>    <p>这里是平台的主页内容...</p>{% endblock %}

这样出来的效果是这样:

基于这段代码,可以继续优化,如:将css抽离、所有html继承base.html、继续微调页面布局等。涉及到的django 模板方法粗略汇总如下:

类别 名称 使用示例 作用说明
HTML 标签 div <div >...</div> 容器元素,用于布局分组
ul/li <ul><li><a href="#"></a></li></ul> 创建水平导航菜单
a <a href="#">首页</a> 创建超链接
h3 <h3>导航菜单</h3> 标题标签,显示侧边栏标题
span <span >...</span> 行内元素,用于右对齐时间信息
p <p>这里是主要内容区域...</p> 段落文本显示
Django 模板方法 {% load static %} {% load static %} 加载静态文件(CSS/JS)的预处理指令
{{ user.username }} 当前用户:{{ user.username }} 输出用户对象的username属性值
{% block content %} {% block content %}<p>...</p>{% endblock %} 定义模板继承的内容区块,子模板可覆盖此部分
(1)html继承
{% extends "base.html" %}
(2)块覆盖
父:<title>{% block title %}定制布局{% endblock %}</title>子:{% block title %}首页 - Algorithm Testing Platform{% endblock %}

如:title使用了块{% block %},这样子页就会覆盖父页的对应内容,这跟内容覆盖是同理的。

(3)将css代码注释掉,用标签link代替
<link rel="stylesheet" href="{% static 'css/base.css' %}">
(4)常用CSS属性
属性 参数类型 示例用法 效果描述
width 长度值、百分比 width: 200px; 设置元素的宽度为200像素。
height 长度值、百分比 height: 100px; 设置元素的高度为100像素。
background-color 颜色值 background-color: #FF0000; 设置元素的背景颜色为红色。
color 颜色值 color: blue; 设置文本颜色为蓝色。
margin 长度值、百分比、关键字 margin: 10px 5px 10px 5px; 设置元素的上、右、下、左外边距分别为10px、5px、10px、5px。
padding 长度值、百分比 padding: 20px; 设置元素的内边距为20像素。
border 长度值、样式、颜色 border: 1px solid black; 设置元素的边框为1像素宽、实线、黑色。
font-size 长度值、百分比、关键字 font-size: 16px; 设置字体大小为16像素。
text-align 关键字 text-align: center; 设置文本水平居中对齐。
display 关键字 display: flex; 将元素设置为弹性盒模型布局。
position 关键字 position: absolute; 将元素设置为绝对定位,相对于最近的已定位祖先元素定位。
top 长度值、百分比 top: 50px; 对于绝对定位或固定定位的元素,设置其上边缘距离包含块上边缘的距离为50像素。
left 长度值、百分比 left: 100px; 对于绝对定位或固定定位的元素,设置其左边缘距离包含块左边缘的距离为100像素。
float 关键字 float: left; 使元素向左浮动。
z-index 整数 z-index: 2; 设置元素的堆叠顺序,数字越大,元素越在顶部。
(5)你可能会遇到的问题

调节前端交互还是需要点经验的,可能需要有点耐心;

一些CSS属性可能在特定情况下不生效,得了解其运行逻辑才能用的起来;

页面不适配的情况在一些情况下会暴露出来,经验不足时不好处理;

django模板继承可能会出现一些情况;

......

(6)前端框架与UI组件

可以考虑前后端分离,如:

简介 | Vue.js (vuejs.org)

Container 布局容器 | Element Plus (element-plus.org)

可以考虑基于CSS的UI组件(本文采用),如:

Bootstrap · 世界上最流行的HTML, CSS, 和JS框架www.bootstrapcn.net

通过CDN引入UI组件:

CDN官网查询Bootstrp版本:https://www.jsdelivr.com/?query=bootstrap

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" integrity="sha256-3gQJhtmj7YnV1fmtbVcnAV6eI4ws0Tr48bVZCThtCGQ=" crossorigin="anonymous"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" integrity="sha256-PI8n5gCcz9cQqQXm3PEtDuPG8qx9oFsFctPg0S5zb8g=" crossorigin="anonymous">

3、图片应用

先搭建底层应用,像堆积木一样网上搭建。正常创建与注册应用后,配置一下图片存储目录:

'''配置媒体文件(用于图片上传)'''# settings.pyMEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

创建模型:

# image_repo/models.pyfrom django.db import modelsclass Image(models.Model):    title = models.CharField(max_length=255)    description = models.TextField(blank=True)    image = models.ImageField(upload_to='images/')  # 图片将存储在media/images/目录    uploaded_at = models.DateTimeField(auto_now_add=True)    def __str__(self):        return self.title

创建视图:

# image_repo/views.pyfrom django.views.generic import ListView, CreateViewfrom .models import Imageclass ImageView(ListView):    model = Image    template_name = 'image_repo/image_list.html'    context_object_name = 'images'class ImageCreateView(CreateView):    model = Image    fields = ['title', 'description', 'image']    template_name = 'image_repo/image_form.html'

配置URL:

# image_repo/urls.pyfrom django.urls import pathfrom .views import ImageView, ImageCreateViewurlpatterns = [    path('', ImageView.as_view(), name='image_list'),    path('add/', ImageCreateView.as_view(), name='image_add'),]

在主项目的urls.py中包含新应用的URL(省略)

在image_repo/templates/image_repo/创建image_list.html (工程目录结构自行调整):

{% extends "base.html" %}{% block content %}<h2>图片仓库</h2><a href="{% url 'image_add' %}">上传新图片</a><ul>  {% for image in images %}    <li>      <h3>{{ image.title }}</h3>      <p>{{ image.description }}</p>      <img src="{{ image.image.url }}" width="200" alt="{{ image.title }}">    </li>  {% endfor %}</ul>{% endblock %}

创建image_form.html:

{% extends "base.html" %}{% block content %}<h2>上传图片</h2><form method="post" enctype="multipart/form-data">  {% csrf_token %}  {{ form.as_p }}  <button type="submit">上传</button></form>{% endblock %}

更新网页布局应用(如:core)的侧边栏菜单,关联链接。

修改若干BUG后可实现添加照片和读取照片,需要继续优化,这里省略。

你可能会遇到的问题:

需要配置媒体文件路由;

修改工程目录;

优化界面;

django自带类的学习;

......

4、其他应用

现在图片数据已经有了,剩下的就是如何围绕数据形成业务流的事情了,这里可以采用这样的设计:

测试项目》测试计划》执行测试》测试归档

(1)测试项目

在测试项目中,可以设计测试计划的数据格式,定义参数化图片应用的命令的运行方式。

(2)测试计划

引用测试项目,可添加测试设备、实现与设备的交互,最终生成测试计划。

(3)执行测试

通过测试挂载服务器,获取服务器的图片数据,并通过测试计划的命令执行,最终生成测试结果

(4)测试归档

即将测试归档到指定地方,与测试计划脱钩。

经过这些应用的添加,最终设计出了算法测试平台!麻雀虽小,五脏俱全!希望这些思路能帮助到大家,just do it !

相关推荐