项目实战——Web自动化测试

news2024/11/27 12:48:06

目录

一、前言及测试用例设计

二、 首页测试(未登录)

三、注册测试

四、对局列表测试

五、排行榜测试

六、对战测试

七、Bot测试

八、测试套件Suite


一、前言及测试用例设计

整个项目已经部署完成,我们历经九九八十一难,但再好的软件,bug也是再所难免,因此从这篇文章开始(也可能只有这一篇文章),我们就对整个项目进行测试,也会包含web自动化测试,因此如果没有学习过测试的同学可以看我之前的博客,废话不多说我们直接开始介绍我们的总体测试:

二、 首页测试(未登录)

 首先在我们的test目录下新建 FrontPageTest 类,由于我们每次都要用到 Chrome 的驱动,因此我们可以把它封装成一个工具类:

package com.kob.backend.tests.common;

import org.openqa.selenium.chrome.ChromeDriver;

public class CommonDriver {
    // 创建驱动对象并返回
    
    private static ChromeDriver driver;
    
    public ChromeDriver getDriver() {
        if (driver == null) driver = new ChromeDriver();
        return driver;
    }
}

为了防止有时出现页面没加载出来的情况,这里添加隐式等待:

driver.manage().timeouts().implicitlyWait(Duration.ofMillis(3000));

FrontPageTest:

package com.chaoyang.tests;

import com.chaoyang.autotest.common.CommonDriver;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

public class FrontPageTest {
    private static ChromeDriver driver = CommonDriver.getDriver();

    /*
    跳转到对应url
     */

    @BeforeAll
    static void getUrl() {
        driver.get("https://app2703.acapp.acwing.com.cn/");
    }


    /*
    校验首页(未登录)是否正确展示元素
     */

    @Test
    void checkFunIsExist() {
        String registerText = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li:nth-child(2) > a")).getText();
        String loginText = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li:nth-child(1) > a")).getText();

        // 检验文本是否符合预期
        Assertions.assertEquals(registerText,"注册");
        Assertions.assertEquals(loginText,"登录");
        driver.quit();
    }
}

三、注册测试

 首先我们要保证我们的状态是未登录的,然后我们去校验“确认密码” 这个元素

 @Test
    void checkFunISExist() {
        String registerText = driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > div:nth-child(3) > label")).getText();
        // 获取注册页面是否包含对应文本,校验文本是否符合预期
        Assertions.assertEquals(registerText,"确认密码");
    }

如何确定我们从注册页面跳转到登录页面呢?我们去校验页面包含“密码”而不含“确认密码”即可, 

void addUser() {
        // 用户名
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过7");
        // 密码
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        // 确认密码
        driver.findElement(By.cssSelector("#confirmedPassword")).sendKeys("123");
        // 提交
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        // 是否跳转到登录界面
        // 包含输入密码 但 不包含 确认密码 即可确定我们已经到达登录界面
        String password = driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > div:nth-child(2) > label")).getText();
        Assertions.assertEquals(password,"密码");
    }

但这样一次添加一个用户测试太慢,这时就要使用到我们的参数化,使用大量数据测试!

不了解参数化的朋友可以看我之前软件测试章节补补功课

添加@ParameterizedTest 注解

添加数据来源注解

这里可以构造一个static 同名方法即可

参数来源 common.ParamsUtil:

package com.chaoyang.tests.common;

public class ParamsUtil {
    private String[] users = new String[] {"姜子牙1","瑞文1","鲁班八号","百里守约1","芈月1"};
    private String[] password = new String[] {"123","321","456","qwer123","哈哈哈"};

    public String getUserName() {
        // 随机返回一个用户名
        int index = (int)(Math.random()*users.length);
        return users[index];
    }

    /*
    密码和确认密码
     */
    public String getPassword() {
        int index = (int)(Math.random()*password.length);
        return  password[index];
    }
}

RegisterTest:

package com.chaoyang.tests;


import com.chaoyang.autotest.common.CommonDriver;
import com.chaoyang.tests.common.ParamsUtil;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.stream.Stream;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegisterTest {
    private static ChromeDriver driver = CommonDriver.getDriver();
    /*
    跳转url
     */
    @BeforeAll
    static void getUrl() {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/register/");
    }

    @Test
    @Order(1)
    void checkFunISExist() {
        String registerText = driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > div:nth-child(3) > label")).getText();
        // 获取注册页面是否包含对应文本,校验文本是否符合预期
        Assertions.assertEquals(registerText,"确认密码");
    }

    /*
    正确注册用户之后跳转到登录页面
     */
    @Order(2)
    @ParameterizedTest()
    @MethodSource()
    void addUser(String name,String password,String confirmedPassword) {
        // 用户名
        driver.findElement(By.cssSelector("#username")).sendKeys(name);
        // 密码
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        // 确认密码
        driver.findElement(By.cssSelector("#confirmedPassword")).sendKeys(confirmedPassword);
        // 提交
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        // 是否跳转到登录界面
        // 包含输入密码 但 不包含 确认密码 即可确定我们已经到达登录界面
        String password1 = driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > div:nth-child(2) > label")).getText();
        Assertions.assertEquals(password1,"密码");
    }

    static Stream<Arguments> addUser() {
        //  给 addUSer 提供数据来源
        ParamsUtil paramsUtil = new ParamsUtil();
        String userName = paramsUtil.getUserName();
        String password = paramsUtil.getPassword();
        return Stream.of(Arguments.arguments(userName,password,password));
    }

    @AfterAll
    static void driverQuit() {
//        driver.quit();
    }
}

 测试结果:

 

成功跳转! 完美实现!

四、对局列表测试

当我们登录之后,测试我们是否可以正常获取所有的对局列表,以及是否可以正常查看回放,以及切页功能是否正常。

 

创建 RecordTest:

package com.chaoyang.tests;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

public class RecordTest {
    private static ChromeDriver driver = new ChromeDriver();

    /*
    跳转到对局回顾 url
     */
    @BeforeAll
    static void getUrl() throws InterruptedException {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/login/");
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#navbarText > ul.navbar-nav.me-auto.mb-2.mb-lg-0 > li:nth-child(2) > a")).click();

    }

    /*
    测试是否正确展示元素
     */
    @Test
    void checkFunIsExist() throws InterruptedException {
        String A = driver.findElement(By.cssSelector("#app > div > div > div > table > thead > tr > th:nth-child(1)")).getText();
        String B = driver.findElement(By.cssSelector("#app > div > div > div > table > thead > tr > th:nth-child(2)")).getText();
        String recordTime = driver.findElement(By.cssSelector("#app > div > div > div > table > thead > tr > th:nth-child(4)")).getText();
        Assertions.assertEquals(A,"A");
        Assertions.assertEquals(B,"B");
        Assertions.assertEquals(recordTime,"对战时间");
        driver.findElement(By.cssSelector("#app > div > div > div > table > tbody > tr:nth-child(2) > td:nth-child(5) > button")).click();
        // 点击之后等待四秒,保证我们的对局回放结束
        Thread.sleep(4000);
    }

    @AfterAll
    static void driverQuit() {
        driver.quit();
    }
}

同时在每一次断言前截图,方便我们留存

CommonDriver中修改:

package com.chaoyang.tests.common;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.chrome.ChromeDriver;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class CommonDriver {
    // 创建驱动对象并返回

    private static ChromeDriver driver;

    public static ChromeDriver getDriver() {
        if (driver == null) {
            driver = new ChromeDriver();
            // 添加隐式等待
            // selenium 是无法等待弹窗的 如果遇到弹窗 可以强制等待
            driver.manage().timeouts().implicitlyWait(Duration.ofMillis(3000));
        }
        return driver;
    }

    public static List<String> getTime() {
        // 文件名格式  20221201-141030+毫秒
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        // 文件夹名称格式 2022-12-01
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyy-MM-dd");
        String filename = sim1.format(System.currentTimeMillis());
        String dirname = sim2.format(System.currentTimeMillis());
        List<String> list = new ArrayList<>();
        list.add(dirname);
        list.add(filename);
        return list;
    }

    /*
    获取屏幕截图
    str:类名下的用例
     */
    public static void getScreenshot(String str) throws IOException {
        List<String> times = getTime();
        String filename = "./src/test/autotest-" + times.get(0) + "/" + str + "-" + times.get(1) + ".png";
        File srcFile = driver.getScreenshotAs(OutputType.FILE);
        // 把截图放到指定路径下
        FileUtils.copyFile(srcFile,new File(filename));
    }
}

 

测试上下切页功能是否正常 

/*
    测试切换页面功能
     */
    @Test
    void checkChange() throws InterruptedException {
        for (int i = 0; i < 3; i ++) {
            driver.findElement(By.cssSelector("#app > div > div > div > nav > ul > li:nth-child(5) > a")).click();
            Thread.sleep(1000);
        }
    }

 

五、排行榜测试

进入排行榜页面之后,我们可以得到所有用户的 rating 分和 用户名 ,在次基础上我们开始测试排行榜是否能正确展示以及上下切换功能是否正常

RankListTest:

package com.chaoyang.tests;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

public class RankListTest {
    private static ChromeDriver driver = new ChromeDriver();

    /*
    跳转到排行榜 url
     */
    @BeforeAll
    static void getUrl() throws InterruptedException {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/login/");
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#navbarText > ul.navbar-nav.me-auto.mb-2.mb-lg-0 > li:nth-child(3) > a")).click();

    }

    /*
    测试是否正确展示元素
     */
    @Test
    void checkFunIsExist() throws InterruptedException {
        String player = driver.findElement(By.cssSelector("#app > div > div > div > table > thead > tr > th:nth-child(1)")).getText();
        String rating = driver.findElement(By.cssSelector("#app > div > div > div > table > thead > tr > th:nth-child(2)")).getText();
        Assertions.assertEquals(player,"玩家");
        Assertions.assertEquals(rating,"天梯分");
    }

    /*
    测试切换页面功能
     */
    @Test
    void checkChange() throws InterruptedException {
        for (int i = 0; i < 3; i ++) {
            driver.findElement(By.cssSelector("#app > div > div > div > nav > ul > li:nth-child(5) > a")).click();
            Thread.sleep(1000);
        }
    }

}

六、Bot测试

当我们的用户处于登录状态时,我们可以通过点击自己的用户名进而创建 Bot 或删除 Bot 

 接下来我们就对于Bot的创建删除等功能进行测试:

切换页面功能:

创建Bot功能: 

package com.chaoyang.tests;

import com.chaoyang.tests.common.CommonDriver;
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BotTest {
    private static ChromeDriver driver = CommonDriver.getDriver();

    /*
    跳转到排行榜 url
     */
    @BeforeAll
    static void getUrl() throws InterruptedException {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/login/");
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#navbarDropdown")).click();

    }

    /*
    测试是否正确展示元素
     */
    @Test
    @Order(1)
    void checkFunIsExist() throws InterruptedException {
        String bot = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(1) > a")).getText();
        String exit = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(3) > a")).getText();
        Assertions.assertEquals(bot,"我的Bot");
        Assertions.assertEquals(exit,"退出");
    }

    /*
    测试切换页面功能 - 到Bot页面
     */
    @Test
    @Order(2)
    void checkChange() throws InterruptedException {
        driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(1) > a")).click();
        String myBot = driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-header > span")).getText();
        Assertions.assertEquals(myBot,"我的Bot");
    }

    /*
    创建Bot 功能
     */
    @Test
    @Order(3)
    void checkCreateBot() {
        driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-header > button")).click();
        // 输入名称,简介,代码等。。。。
        driver.findElement(By.cssSelector("#add-bot-title")).sendKeys("名称1");
        driver.findElement(By.cssSelector("#add-bot-description")).sendKeys("简介1");
        driver.findElement(By.cssSelector("#add-bot-btn > div > div > div.modal-footer > button.btn.btn-primary")).click();
    }
}

修改Bot功能:

 

删除Bot功能:

 

成功删除~ 

package com.chaoyang.tests;

import com.chaoyang.tests.common.CommonDriver;
import org.junit.jupiter.api.*;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BotTest {
    private static ChromeDriver driver = CommonDriver.getDriver();

    /*
    跳转到排行榜 url
     */
    @BeforeAll
    static void getUrl() throws InterruptedException {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/login/");
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#navbarDropdown")).click();

    }

    /*
    测试是否正确展示元素
     */
    @Test
    @Order(1)
    void checkFunIsExist() throws InterruptedException {
        String bot = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(1) > a")).getText();
        String exit = driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(3) > a")).getText();
        Assertions.assertEquals(bot,"我的Bot");
        Assertions.assertEquals(exit,"退出");
    }

    /*
    测试切换页面功能 - 到Bot页面
     */
    @Test
    @Order(2)
    void checkChange() throws InterruptedException {
        driver.findElement(By.cssSelector("#navbarText > ul:nth-child(2) > li > ul > li:nth-child(1) > a")).click();
        String myBot = driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-header > span")).getText();
        Assertions.assertEquals(myBot,"我的Bot");
    }

    /*
    创建Bot 功能
     */
    @Test
    @Order(3)
    void checkCreateBot() {
        driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-header > button")).click();
        // 输入名称,简介,代码等。。。。
        driver.findElement(By.cssSelector("#add-bot-title")).sendKeys("名称1");
        driver.findElement(By.cssSelector("#add-bot-description")).sendKeys("简介1");
        driver.findElement(By.cssSelector("#add-bot-btn > div > div > div.modal-footer > button.btn.btn-primary")).click();
        driver.findElement(By.cssSelector("#add-bot-btn > div > div > div.modal-footer > button.btn.btn-secondary")).click();
        Alert alert = driver.switchTo().alert();
        alert.dismiss();
    }

    @Test
    @Order(4)
    void checkUpdate() {
        driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-body > table > tbody > tr > td:nth-child(3) > button.btn.btn-secondary")).click();
        driver.findElement(By.cssSelector("#add-bot-title")).sendKeys("名称1");
        driver.findElement(By.cssSelector("#add-bot-description")).sendKeys("简介1");
        driver.findElement(By.cssSelector("#add-bot-btn > div > div > div.modal-footer > button.btn.btn-primary")).click();
        driver.findElement(By.cssSelector("#add-bot-btn > div > div > div.modal-footer > button.btn.btn-secondary")).click();
    }

    @Test
    @Order(5)
    void checkDelete() {
        driver.findElement(By.cssSelector("#app > div > div > div.col-9 > div > div.card-body > table > tbody > tr > td:nth-child(3) > button.btn.btn-danger")).click();
    }
}

七、对战测试

当我们进入到对战页面后,我们可以开始匹配进入游戏,也可以选择让我们的代码替我们出战,此时我们需要测试软件是否能正确展示我们的Bot并且可以选择人或者bot 出战!

展示测试:

下拉框测试(Bot列表):

 

 开始匹配功能测试:

 

 

package com.chaoyang.tests;

import com.chaoyang.tests.common.CommonDriver;
import org.junit.jupiter.api.*;
import org.junit.platform.suite.api.SelectClasses;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class PkTest {
    private static ChromeDriver driver = CommonDriver.getDriver();

    /*
    跳转到pk url (首页默认就是pk)
     */
    @BeforeAll
    static void getUrl() throws InterruptedException {
        driver.get("https://app2703.acapp.acwing.com.cn/user/account/login/");
        driver.findElement(By.cssSelector("#username")).sendKeys("杨过1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#app > div > div > div > div > div > form > button")).click();
    }

    /*
    测试是否正确展示元素
     */
    @Test
    @Order(1)
    void checkFunIsExist() throws InterruptedException {
        String pk = driver.findElement(By.cssSelector("#app > div > div > div.col-12 > button")).getText();
        Assertions.assertEquals(pk,"开始匹配");
    }

    /*
    测试切换bot功能
     */
    @Test
    @Order(2)
    void checkChange() throws InterruptedException {
        WebElement ele = driver.findElement(By.cssSelector("#app > div > div > div:nth-child(2) > div > select"));
        Select select = new Select(ele);
        select.selectByIndex(0);
    }

    /*
    测试开始匹配功能
     */
    @Test
    @Order(3)
    void checkPK() {
        driver.findElement(By.cssSelector("#app > div > div > div.col-12 > button")).click();
    }

}

 

八、测试套件Suite

一个一个测试很麻烦,我们把所有的测试类集成到一个类RunSuite中:

删除我们之前每个类中的driver.quit()

因此我们把这个driver.quit专门抽取为一个类,放在最后执行即可

package com.chaoyang.tests;

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({FrontPageTest.class,RegisterTest.class,RecordTest.class,DriverQuitTest.class})
public class RunSuite {

}

 

截图成功! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

英国Top20名校更偏爱IB申请党?

IB的全球超高认可度相信大家都有共识&#xff0c;英国大学对于A-Level、IB成绩都持认可态度。 但多数人会认为A-Level成绩申请英国名校会比IB更有优势&#xff0c;事实果真如此吗&#xff1f;接下来通过官方给出的数据&#xff0c;我们来一探究竟~ 01英国Top20名校更偏爱IB学生…

Linux的十个常用命令

目录 1、ls 2、pwd 3、cd 4、touch 5、cat 6、echo 7、mkdir 8、rm 9、mv 10、cp 1、ls ls命令用于显示目录中的文件信息. 格式&#xff1a;ls [选项] [文件] 参数&#xff1a; -a 显示所有文件及目录 (. 开头的隐藏文件也会列出)-l 除文件名称外&#xff0c;亦将文件型…

点云缩放(附open3d python代码)

1/ numpy 数组方法 通过将点云数组乘以一个缩放因子来改变大小, 同时通过加法运算实现质心平移。points = points/2.0#缩小到原来的一半 points[:, 0] = points[:, 0] + 20#质心平移到x=20处2/ open3d的缩放函数为scale,包含两个参数。 第一个参数是缩放的比例,即放大的倍数…

Kafka怎样完成建立和Broker之间的连接?

文章目录NetworkClient初始化1.基于Java NIO SocketChannel封装KafkaChannel2.Kafka提供的Selector是如何初始化跟Broker之间的连接的2.1 初始化SocketChannel&#xff0c;发起连接请求2.2 将发起连接请求后的SocketChannel缓存起来3.万能poll()方法之前的准备工作4. 通过不断轮…

win11电脑加密文件夹的两种方法

为了保证隐私安全&#xff0c;很多用户都会给文件夹设置密码&#xff0c;只有输对密码才能进入文件夹&#xff0c;那么升级到Win11新系统要怎么操作呢&#xff1f;下面小编就给大家带来两种加密方式&#xff0c;任你挑选。 方法一&#xff1a; 1、首先去找到要加密的文件夹。 2…

Java企业微信对接

最近项目中要对接企业微信&#xff0c;实现通讯录数据同步&#xff0c;即在企业端添加编辑删除用户&#xff0c;部门数据要同步到微信端&#xff0c;同时微信端添加编辑删除用户&#xff0c;部门数据要同步到企业端&#xff0c;实现数据同步功能&#xff0c;需要调用企业微信AP…

DDD的简单落地实现

目录 概述 和微服务的联系 具体划分 遵循依赖倒置原则 其他规范 具体实现代码 总结 概述 领域式驱动&#xff08;DDD&#xff09; 这种模式的核心就是根据功能去划分领域&#xff0c;然后在这个领域内只做这个领域的事情。 和微服务的联系 和微服务有什么类似的地方&am…

PyTorch 新库 TorchMultimodal 使用说明:将多模态通用模型 FLAVA 扩展到 100 亿参数

先前的文章中&#xff0c;我们介绍了 TorchMultimodal&#xff0c;今天我们将从一个具体案例出发&#xff0c;演示如何在 Torch Distributed 技术加持下&#xff0c;在 TorchMultimodal 库中扩展多模态基础模型。 近年来&#xff0c;大模型已成为一个备受关注的研究领域。以自然…

GOM传奇引擎登录器商业版与免费版的区别

商业版与免费版登录器的区别&#xff1a; 1商业版自定义界面功能可以保存配置 2商业版登录器支持读取二次加密的Pak。需要购买Pak二次加密工具。 3商业版增加数字证书&#xff0c;防止杀毒软件误报 4商业版支持163博客远程列表&#xff0c;列表首尾需要$BEGIN $END关键字 5商业…

如何提高网站安全防护?

网站安全是网站建设后非常关键的一个问题&#xff0c;是不可以忽视的&#xff0c;一个安全性不高的网站对于网站的危害是很多的&#xff0c;网站安全性不高的网站容易被攻击、容易被挂马、容易造成网站数据泄露&#xff0c;下面安全狗小编来跟大家聊一下网站安全性该如何提高。…

Git常见操作

什么是Git 简单说&#xff0c;git就是版本管理工具。 Git解决的问题 试想一下&#xff0c;你是公司的设计人员。老板要求你设计一份海报。你花了3天时间&#xff0c;画好了&#xff0c;并命名为海报1.0.然后你给老板看&#xff0c;老板看了说“设计的很好&#xff0c;要是能…

将 Vue.js 项目部署至静态网站托管,并开启 Gzip 压缩

摘要&#xff1a;关于使用 Nginx 开启静态网站 Gzip 压缩的教程已经有很多了&#xff0c;但是好像没几个讲怎么在对象存储的静态网站中开启 Gzip 压缩。其实也不复杂&#xff0c;我们一起来看下~本文分享自华为云社区《将 Vue.js 项目部署至静态网站托管&#xff0c;并开启 Gzi…

基于模糊推理的滑膜控制

目录 前言 1.系统描述 2.控制器设计 3.模糊推理估计不确定f 3.1构造模糊系统 3.2模糊推理过程 3.3 自适应律设计 4.仿真分析 4.1仿真模型 4.2仿真结果 5.总结 前言 在一般的建模仿真中&#xff0c;我们假设模型都是可以用数学模型描述出来的是确定的&#xff0c;称…

Flink系列之Flink集群搭建

title: Flink系列 二、Flink集群搭建 2.1 Flink的Standalone模式集群安装 1、上传解压重命名 [roothadoop10 software]# tar -zxvf flink-1.14.3-bin-scala_2.12.tgz [roothadoop10 software]# mv flink-1.14.3 flink2、进入到解压之后的目录里面修改配置文件flink-conf.yam…

Hash 的定义

Hash&#xff0c;一般翻译做散列、杂凑&#xff0c;或音译为哈希。 这句话就是很多混乱的根源。 笔者还是比较时候直接使用 哈希这个翻译&#xff0c;或者干脆不翻译。 混乱来源 在查看很多资料的时候&#xff0c;经常会看到最多的一个词就是散列算法。 如果不深入追究下的…

PyQt5 数据库处理

PyQt5 数据库处理SQLite介绍连接数据库执行SQL语句创建SQLite数据库关闭窗口时断开SQLite连接数据库模型视图列表模式显示数据栅格模式分页显示数据SQLite介绍 SQLite是一个轻量级的数据库&#xff0c;实现了自给自足、无服务器、零配置、事务性的SQL数据库引擎。 下载地址 安…

深入理解ThreadLocal源码

1. 预备知识&#xff1a;强软弱虚引用 在Java中有四种引用的类型&#xff1a;强引用、软引用、弱引用、虚引用。 设计这四种引用的目的是可以用程序员通过代码的方式来决定对象的生命周期&#xff0c;方便GC。 强引用 强引用是程序代码中最广泛使用的引用&#xff0c;如下&a…

如何通过股票行情接口查询财务数据?

我们做交易&#xff0c;有时候还是需要用到一些上市公司的财务数据的&#xff0c;有什么板块可以快速获取财务数据呢&#xff1f;那肯定就是利用股票行情接口进行查询了&#xff0c;那具体要怎么做呢&#xff1f;下面这组代码可以了解一下&#xff1a; get_fundamentals - 查询…

Markdown格式表情包大全最新整理分享

Markdown表情包一、前言❤️二、Emoji表情大全&#x1f46e;People&#xff08;人物&#xff09;❄️Nature&#xff08;自然&#xff09;&#x1f514;Objects&#xff08;物体&#xff09;&#x1f3e0;Places&#xff08;地点&#xff09;&#x1f51f;Symbols&#xff08;符…

如何选择独立站ERP系统?

在选择ERP系统时所需要考虑以下几个问题&#xff0c;首先是看看ERP的操作流程是否简单明了。ERP最核心的作用就是提升工作效率&#xff0c;如果操作流程过于复杂&#xff0c;反倒是会增加学习成本&#xff0c;因此快速上手是先决条件。 其次便是需要看看功能是否符合卖家的需…