用户管理系统-自动化测试

news2025/1/19 2:37:13

文章目录

  • 1. 思维导图编写 Web 自动化测试用例
  • 2. 创建测试项目
  • 3. 根据思维导图设计用户管理系统自动化测试用例
    • 3.1 准备工具类
    • 3.2 测试登录页面
    • 3.3 测试用户列表页
    • 3.4 测试添加用户页
    • 3.5 测试修改用户页
    • 3.6 未登录状态
  • 4. 自动化测试项目总结
    • 4.1 自动化测试项目实现步骤
    • 4.2 当前项目亮点

本篇针对我之前写的项目进行自动化测试。
项目链接: 用户管理系统(用户名:admin;密码:admin)

1. 思维导图编写 Web 自动化测试用例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5pmewL7O-1681561315211)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1681560620352.png)]

2. 创建测试项目

  1. 创建 Maven 项目
  2. 在 test 包下编写相关测试代码
  3. 导入自动化测试需要的相关依赖

在 pom.xml 中引入自动化测试相关依赖:

    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0</version>
        </dependency>
        <!-- 保存屏幕截图文件需要用到的包-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- Junit 中 参数化测试 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <!-- junit 中 测试套件 -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

3. 根据思维导图设计用户管理系统自动化测试用例

3.1 准备工具类

在 common 包下创建 AutoTestUtils 类,该类需要提供以下功能:

  1. 创建驱动对象,提供给页面使用。
  2. 创建隐式等待,作用于驱动对象的整个生命周期。
  3. 提供屏幕截图方法,以及保存截图的格式。
/**
 * @Description: 创建驱动对象;提供屏幕截图方法
 * @Date 2023/4/15 9:59
 * @Author:
 */
public class AutoTestUtils {
    public static EdgeDriver driver;

    /**
     * @param : 创建驱动对象
     * @return EdgeDriver
     * @description TODO
     */
    public static EdgeDriver createDriver() {
        EdgeOptions options = new EdgeOptions();
        options.addArguments("-remote-allow-origins=*");
        // 驱动对象没有创建
        if(driver == null) {
            driver = new EdgeDriver(options);
            // 创建隐式等待
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
        }
        // 驱动对象已经创建好了
        return driver;
    }

    /**
     * @param str: 类名
     * @return void
     * @description 获取屏幕截图,把所有的用例执行的结果都保存下来
     */
    public void getScreenShot(String str) throws IOException {
        List<String> list = getTime();
        // ./src/test/java/com/usermanagerWebAutoTest/日期/类名_日期_时间.png
        String filename = "./src/test/java/com/usermanagerWebAutoTest/" + list.get(0) +
                "/" + str + "_" + list.get(1) + ".png";
        // 进行屏幕截图
        File srcFile = driver.getScreenshotAs(OutputType.FILE);
        // 将屏幕截图生成的图片放到指定路径下
        FileUtils.copyFile(srcFile,new File(filename));
    }

    public List<String> getTime() {
        // 文件格式 2023-04-15/2023-04-15_12:36:00
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        // 以天的维度按文件夹进行保存
        String dirname = sim1.format(System.currentTimeMillis());
        String filename = sim2.format(System.currentTimeMillis());
        List<String> list = new ArrayList<>();
        list.add(dirname);
        list.add(filename);
        return list;
    }
}

在 Tests 包下创建 DriverQuitTest 类,该类的主要作用是用来释放驱动

/**
 * @Description: 释放驱动
 * @Date 2023/4/15 9:59
 * @Author:
 */
public class DriverQuitTest extends AutoTestUtils {
    public static EdgeDriver driver = createDriver();

    @Test
    void driverQuit() {
        driver.quit();
    }
}

在 Tests 包下创建 runSuite 类,该类的就是测试套件

/**
 * @Description: 测试套件
 * @Date 2023/4/15 10:00
 * @Author:
 */
@Suite
@SelectClasses({UserNoLoginTest.class,UserLoginTest.class,UserListTest.class,AddUserTest.class,UpdateUserTest.class,DriverQuitTest.class})
public class runSuite {
}

3.2 测试登录页面

创建 UserLoginTest 类,该类的测试用例有 6 个。

  • 页面是否可以正常打开
  • 不输入用户名,输入密码,点击登录
  • 输入用户名,不输入密码,点击登录
  • 用户名和密码都不输入,点击登录
  • 输入错误的用户名和密码,点击登录
  • 输入正确的用户名和密码,点击登录
/**
 * @Description: 测试登录页面
 * @Date 2023/4/15 10:00
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserLoginTest extends AutoTestUtils {
    // 1. 访问浏览器对象  2. 访问登录页面的 URL
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:8080/login.html");
    }

    /**
     * @param :
     * @return void
     * @description 检查页面是否可以正常打开
     */
    @Test
    @Order(1)
    void loginPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#body > div > h3"));
        driver.findElement(By.cssSelector("#loginname"));
        driver.findElement(By.cssSelector("#submit"));
        getScreenShot(getClass().getName());
    }

    /**
     * @param password:
     * @return void
     * @description 不输入用户名,输入密码,点击登录
     */
    @ParameterizedTest
    @CsvSource({"111"})
    @Order(2)
    void loginFailUsernameNull(String password) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#loginname")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @param username:
     * @return void
     * @description 输入用户名,不输入密码,点击登录
     */
    @ParameterizedTest
    @CsvSource({"111"})
    @Order(3)
    void loginFailPasswordNull(String username) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#loginname")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#loginname")).sendKeys(username);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description 用户名和密码都不输入,点击登录
     */
    @Test
    @Order(4)
    void loginFailUsernameAndPasswordNull() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#loginname")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description 输入错误的用户名和密码,点击登录
     */
    @ParameterizedTest
    @CsvSource({"1111,1111"})
    @Order(5)
    void loginFail(String username,String password) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#loginname")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#loginname")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录失败结果检测
        Thread.sleep(1000);
        // 切换到弹窗进行处理
        Alert alert = driver.switchTo().alert();
        // 点击确认
        alert.accept();
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description 输入正确的用户名和密码,点击登录
     */
    @ParameterizedTest
    @CsvSource({"admin,admin"})
    @Order(6)
    void loginSucced(String username,String password) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#loginname")).clear(); // 先清空一下
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#loginname")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        // 登录成功检测,如果跳转到用户列表页,才算是成功的
        driver.findElement(By.cssSelector("#body > div > h3"));
        Thread.sleep(2000);
        getScreenShot(getClass().getName());
        // 这里页面跳转了,重新返回到登录页面
        driver.navigate().back();
    }
}

3.3 测试用户列表页

创建 UserListTest 类,该类的测试用例有 4 个(默认登录状态下)。

  • 页面内容显示是否正常
  • 是否能跳转到添加用户页
  • 是否能跳转到修改用户页
  • 查询用户功能是否正常
/**
 * @Description: 测试用户列表页
 * @Date 2023/4/15 10:00
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserListTest extends AutoTestUtils {
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:8080/list.html");
    }

    /**
     * @return void
     * @description 检查页面内容显示是否正常
     */
    @Test
    @Order(1)
    void ListPageLoadRight() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#submit1"));
        driver.findElement(By.cssSelector("#body > div > table > tbody:nth-child(1) > tr > th:nth-child(1)"));
        driver.findElement(By.cssSelector("#all > li:nth-child(1) > a"));
        driver.findElement(By.cssSelector("#body > div > div:nth-child(3) > a:nth-child(1)"));
        driver.findElement(By.cssSelector("#delete"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description: 检测添加用户按钮链接跳转正常
     */
    @Test
    @Order(2)
    void LinkJumpAdd() throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#body > div > div:nth-child(3) > a:nth-child(1)")).click();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        driver.navigate().back();
    }

    /**
     * @return void
     * @description: 检测修改用户按钮链接跳转正常
     */
    @Test
    @Order(3)
    void LinkJumpUpdate() throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#info > tr:nth-child(1) > th:nth-child(10) > a:nth-child(1)")).click();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        driver.navigate().back();
    }

    /**
     * @return void
     * @description: 检测查询用户功能是否正常
     */
    @ParameterizedTest
    @CsvSource({"超级管理员"})
    @Order(4)
    void SelectUser(String name) throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#ipt_name")).sendKeys(name);
        driver.findElement(By.cssSelector("#submit1")).click();
        driver.findElement(By.cssSelector("#info > tr > th:nth-child(3)"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }
}

3.4 测试添加用户页

创建 AddUserTest 类,该类的测试用例有 5 个(默认登录状态下)。

  • 页面内容是否显示正常
  • 管理员权限为超管,填写用户信息时,如果用户名重复,不能提交。
  • 管理员权限为超管,填写用户信息时,如果用户名不重复,可以提交。
  • 管理员权限为普通用户,可以正常填写信息,但不可以提交。
  • 返回链接跳转正常。
/**
 * @Description: 测试添加用户页
 * @Date 2023/4/15 10:00
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AddUserTest extends AutoTestUtils {
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:8080/add.html");
    }

    /**
     * @return void
     * @description 检查页面内容显示是否正常
     */
    @Test
    @Order(1)
    void AddPageLoadRight() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username"));
        driver.findElement(By.cssSelector("#password"));
        driver.findElement(By.cssSelector("#btn_sub"));
        driver.findElement(By.cssSelector("#btn_back"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description :管理员权限为超管,填写用户信息时,如果用户名重复,不能提交。
     */
    @ParameterizedTest
    @CsvSource({"111,111,111,111,20,111,111"})
    @Order(2)
    void SuperTube_UserRepeatFail(String user,String login,String pass,String pass2,String age,String qq,String em) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#username")).sendKeys(user);
        driver.findElement(By.cssSelector("#loginname")).sendKeys(login);
        driver.findElement(By.cssSelector("#password")).sendKeys(pass);
        driver.findElement(By.cssSelector("#password2")).sendKeys(pass2);
        driver.findElement(By.cssSelector("#age")).sendKeys(age);
        driver.findElement(By.cssSelector("#qq")).sendKeys(qq);
        driver.findElement(By.cssSelector("#email")).sendKeys(em);
        driver.findElement(By.cssSelector("#btn_sub")).click();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description :管理员权限为超管,填写用户信息时,如果用户名不重复,可以提交。
     */
    @ParameterizedTest
    @CsvSource({"111,111,20,111,111"})
    @Order(3)
    void SuperTube_UserRepeatSucc(String pass,String pass2,String age,String qq,String em) throws InterruptedException, IOException {
        Random random = new Random();
        int n = random.nextInt(100000);
        driver.findElement(By.cssSelector("#username")).sendKeys(String.valueOf(n));
        driver.findElement(By.cssSelector("#loginname")).sendKeys(String.valueOf(n));
        driver.findElement(By.cssSelector("#password")).sendKeys(pass);
        driver.findElement(By.cssSelector("#password2")).sendKeys(pass2);
        driver.findElement(By.cssSelector("#age")).sendKeys(age);
        driver.findElement(By.cssSelector("#qq")).sendKeys(qq);
        driver.findElement(By.cssSelector("#email")).sendKeys(em);
        driver.findElement(By.cssSelector("#btn_sub")).click();
        Thread.sleep(1000);
        Alert alert = driver.switchTo().alert();
        alert.accept();
        Thread.sleep(1000);
        Alert alert2 = driver.switchTo().alert();
        alert2.dismiss();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        driver.navigate().back();
    }

    /**
     * @return void
     * @description: 返回链接跳转正常。
     */
    @Test
    @Order(4)
    void ReturnLinkJumpSucc() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#btn_back")).click();
        driver.findElement(By.cssSelector("#body > div > h3"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }
}

3.5 测试修改用户页

创建 UpdateUserTest 类,该类的测试用例有 5 个(默认登录状态下)。

  • 页面内容是否显示正常。
  • 管理员权限为超管,修改用户信息时,如果密码和确认密码栏不相同,不能提交。
  • 管理员权限为超管,修改用户信息时,如果密码和确认密码栏相同,可以提交。
  • 管理员权限为普通用户,可以正常修改信息,但不能提交。
  • 返回链接跳转正常,重置按钮功能正常。
/**
 * @Description: 测试修改用户页
 * @Date 2023/4/15 10:01
 * @Author:
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UpdateUserTest extends AutoTestUtils {

    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl() {
        driver.get("http://47.108.57.239:8080/update.html?uid=3");
    }

    /**
     * @return void
     * @description 检查页面内容显示是否正常
     */
    @Test
    @Order(1)
    void AddPageLoadRight() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#body > div > h3"));
        String text = driver.findElement(By.cssSelector("#loginname")).getAttribute("value");
        Assertions.assertEquals("111",text);
        driver.findElement(By.cssSelector("#btn_sub"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description :管理员权限为超管,修改用户信息时,如果密码和确认密码栏不相同,不能提交。
     */
    @ParameterizedTest
    @CsvSource({"1234,111,111666"})
    @Order(2)
    void SuperTube_PassInequalityFail(String pass,String pass2,String em) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#password")).sendKeys(pass);
        driver.findElement(By.cssSelector("#password2")).sendKeys(pass2);
        driver.findElement(By.cssSelector("#email")).sendKeys(em);
        driver.findElement(By.cssSelector("#btn_sub")).click();
        Thread.sleep(1000);
        Alert alert = driver.switchTo().alert();
        alert.accept();
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        driver.findElement(By.cssSelector("#btn_reset")).click();
    }

    /**
     * @return void
     * @description :管理员权限为超管,修改用户信息时,如果密码和确认密码栏相同,可以提交。
     */
    @ParameterizedTest
    @CsvSource({"234567,234567,1111111"})
    @Order(3)
    void SuperTube_PassIdenticalSucc(String pass,String pass2,String em) throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#password")).sendKeys(pass);
        driver.findElement(By.cssSelector("#password2")).sendKeys(pass2);
        driver.findElement(By.cssSelector("#email")).sendKeys(em);
        driver.findElement(By.cssSelector("#btn_sub")).click();
        Thread.sleep(1000);
        Alert alert = driver.switchTo().alert();
        alert.accept();
        getScreenShot(getClass().getName());
        driver.navigate().back();
    }

    /**
     * @return void
     * @description: 返回链接跳转正常。
     */
    @Test
    @Order(4)
    void ReturnLinkJumpSucc() throws InterruptedException, IOException {
        driver.findElement(By.cssSelector("#btn_back")).click();
        String text = driver.findElement(By.cssSelector("#body > div > h3")).getText();
        Assertions.assertEquals("用户信息列表",text);
        getScreenShot(getClass().getName());
    }
}

3.6 未登录状态

创建 UserNoLoginTest 类,该类的测试用例有 3 个。

  • 跳转到用户列表页。
  • 跳转到添加用户页。
  • 跳转到修改用户页。
/**
 * @Description: 测试未登录状态下
 * @Date 2023/4/15 10:01
 * @Author:
 */
public class UserNoLoginTest extends AutoTestUtils {
    public static EdgeDriver driver = createDriver();

    /**
     * @param :
     * @return void
     * @description 未登录状态跳转到用户列表页
     */
    @Test
    void JumpUserListFail() throws InterruptedException, IOException {
        driver.get("http://47.108.57.239:8080/list.html");
        Thread.sleep(1000);
        String text = driver.findElement(By.cssSelector("#body > div > h3")).getText();
        Assertions.assertEquals("管理员登录",text);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description 未登录状态跳转到添加用户页
     */
    @Test
    void JumpAddUserFail() throws InterruptedException, IOException {
        driver.get("http://47.108.57.239:8080/add.html");
        Thread.sleep(1000);
        String text = driver.findElement(By.cssSelector("#body > div > h3")).getText();
        Assertions.assertEquals("管理员登录",text);
        getScreenShot(getClass().getName());
    }

    /**
     * @return void
     * @description 未登录状态跳转到修改用户页
     */
    @Test
    void JumpUpdateUserFail() throws InterruptedException, IOException {
        driver.get("http://47.108.57.239:8080/update.html");
        Thread.sleep(1000);
        String text = driver.findElement(By.cssSelector("#body > div > h3")).getText();
        Assertions.assertEquals("管理员登录",text);
        getScreenShot(getClass().getName());
    }
}

4. 自动化测试项目总结

4.1 自动化测试项目实现步骤

  1. 根据自己的项目,用思维导图的方式设计出UI自动化测试用例;
  2. 结合自己编写的测试用例,使用 Selenium4 自动化测试工具和 Junit5 单元测试框框架,实现 Web 自动化测试;
  3. 然后就是进行模块划分,主要是按照两个包划分,一个是工具类包,用来创建驱动对象和提供屏幕截图方法,还有一个包是测试用例包,这个包下面的类是按照以页面为单位编写的测试代码,避免了每个方法都要创建驱动对象的麻烦,最后将这些测试类加入到测试套件中。
  4. 注意不要等项目整个代码写完后再进行测试,最好是写一部分代码测试一下。比如我编写代码时写完一个页面的测试用例后,再进行测试。

4.2 当前项目亮点

  • 只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费
  • 使用了 Junit5 中提供的注解:避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率
  • 测试套件:降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例
  • 使用了等待:隐式等待+强制等待(提高了自动化运行效率,提高了自动化的稳定性)
  • 使用屏幕截图:方便问题的追溯以及问题的解决
  • 使用参数化:保持用例的简洁,提高代码的可读性

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

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

相关文章

图数据库驱动的基础设施运维实操

本文系图技术在大型、复杂基础设施之中 SRE/DevOps 的实践参考&#xff0c;并以 OpenStack 系统之上的图数据库增强的运维案例为例&#xff0c;揭示图数据库、图算法在智能运维上的应用。本文所有示例代码开源。 最近&#xff0c;有些尚未使用过图技术、DevOps/Infra 领域的工程…

除了Java,还可以培训学习哪些IT技术?

除了Java&#xff0c;还可以培训学习哪些IT技术&#xff1f;转行IT学Java似乎已经成为很多人的首选&#xff0c;原因无非是开发技术含量高、开发有前景、开发是一个互联网企业的核心岗位&#xff0c;最重要的是开发薪资待遇高。但其实只单纯因为薪资选择Java的话&#xff0c;小…

Flask数据迁移详细步骤

数据迁移详细步骤&#xff1a; 1. 安装好数据迁移的包 flask-sqlalchemy和flask-migrate Flask模型相关包安装 2. 在exts.py中初始化Migrate和SQLAlchemy 3. 在models中定义好模型 4. 在views.py中一定要导入models模块 from .models import * 5. 配置好数据库&#xff08;sql…

MYSQL笔记01 数据库概述,SELECT语句,运算符,排序与分页,多表查询

数据库概述 为什么要使用数据库 持久化&#xff1a;把数据保存在可掉电式存储设备中以供之后使用。大多数情况下&#xff0c;特别是企业级应用&#xff0c;数据持久化意味着将内存中的数据保存到硬盘上加以"固化"&#xff0c;而持久化的实现过程大多通过各种关系数据…

详解 23 种设计模式(多图 + 代码)

创建型模式 创建型模式的作用就是创建对象&#xff0c;说到创建一个对象&#xff0c;最熟悉的就是 new 一个对象&#xff0c;然后 set 相关属性。但是&#xff0c;在很多场景下&#xff0c;我们需要给客户端提供更加友好的创建对象的方式&#xff0c;尤其是那种我们定义了类&a…

每68个孩子里,就有一个自闭症,“来自星星的孩子”,离我们很近

今年4月2日是世界上第14个“世界自闭症日”。自闭症儿童&#xff0c;又称“星星儿童”&#xff0c;形容他们像遥远的星星一样独自在夜空中闪耀。自闭症并不少见根据世卫组织的调查&#xff0c;世界上每160名儿童中就有一人患有自闭症。根据《中国自闭症&#xff08;自闭症&…

【从零开始学Skynet】基础篇(四):网络模块常用API

游戏服务端要处理客户端请求&#xff0c;作为服务端引擎&#xff0c;网络编程也是Skynet的核心功能。1、学习网络模块 skynet.socket模块提供了网络编程的API&#xff0c;常用的API如下表所示&#xff1a;Lua API说明socket.listen(address ,port)监听一个端口&#xff0c;返回…

你需要知道的企业网页制作流程

企业网页制作是企业建立线上形象和宣传的重要手段之一&#xff0c;它不仅可以提高企业的品牌知名度&#xff0c;还可以扩大企业的影响力和拓展客户群。下面&#xff0c;我们将介绍一些企业网页制作的基本流程和技巧&#xff0c;并结合一个案例来详细解析。 企业网页制作的基本…

【DT】蒸脱机的结构和工作原理

DT蒸脱机的结构和工作原理什么是DTDT结构图工作过程什么是DT DT 蒸脱机&#xff08;DesolventazationerToaster&#xff09;&#xff0c;根据英文名可以看出来&#xff0c;他的作用是脱溶、烘烤。用于蒸脱湿豆粕中的溶剂。 大豆油生产工艺有2种&#xff1a;压榨油的加工工艺是…

C++标准库--IO库(Primer C++ 第五版 · 阅读笔记)

C标准库--IO库(Primer C 第五版 阅读笔记&#xff09;第8章 IO库8.1、IO类8.2、文件输入输出8.3、string流总结&#xff1a;第8章 IO库 8.1、IO类 为了支持这些不同种类的IO处理操作&#xff0c;在istream和ostream之外&#xff0c;标准库还定义了其他一些IO类型。 如下图分…

Java中的注解,自定义注解

文章目录1. 注解概述2. 注解与注释3. 注解的重要性4. 常见的Annotation作用4.1 生成文档相关的注解4.2 在编译时进行格式检查(JDK内置的三个基本注解)5. 元注解6. 自定义注解6.1 定义自定义注解6.2 使用自定义注解6.3 读取和处理自定义注解框架 注解 反射 设计模式 1. 注解概…

PC安装虚拟化平台趟坑记录

合肥先进光源永磁多极铁电机控制系统的规划 Zstack EPICS Archiver在小课题组的使用经验 神仙同学的永磁四极铁样铁已经开始加工了&#xff0c;过一个月左右就要回来了&#xff0c;电机控制部分交给留国做&#xff0c;调试的也差不多了。项目买过一台工控机&#xff0c;到时候…

STM32F407ZGT6实现OLED显示屏

1、调试工具 2、OLED简介 3、硬件电路&#xff08;接线&#xff09; 本文采用7脚,倘若采用4脚&#xff0c;资料代码啥的可以在江科大B站视频下载&#xff1a; 资料下载&#xff1a;https://pan.baidu.com/s/1SqKyKr5Fsl_9gBJi8aVxTw&#xff0c; 提取码&#xff1a;8kzh&#x…

日本首相会见奥特曼,考虑引入 ChatGPT 技术

文&#xff5c;小戏卖萌屋日本4月12日电&#xff0c;日本国第101任首相&#xff0c;日本自民党总裁岸田文雄4月10日于东京会见了奥特曼先生&#xff0c;二人就 ChatGPT 引入日本的可能性问题交换了意见并进行了深入的讨论。奥特曼先生表示&#xff0c;希望为日本人创造伟大的东…

NumPy 秘籍中文第二版:三、掌握常用函数

原文&#xff1a;NumPy Cookbook - Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 在本章中&#xff0c;我们将介绍许多常用函数&#xff1a; sqrt()&#xff0c;log()&#xff0c;arange()&#xff0c;astype()和sum()ceil()&#xff0c;modf()&…

如何突破LinkedIn领英限制,导出非好友邮箱等社交方式

相信做外贸的朋友都有使用过Linkedin&#xff0c;如果还没有使用过的话&#xff0c;我只能说您错过一个很好的平台。只要是厉害的外贸人都特别擅长用Linkedin找客户。 那为什么说Linkedin是外贸业务员开发客户最有效的途径呢&#xff1f;主要基于以下几点&#xff1a; 第一&a…

常见的相似度计算方式

1.欧氏距离(Euclidean Distance) 欧氏距离(也称欧几里得度量)指在mmm维空间中两个点之间的真实距离&#xff0c;或者向量的自然长度(即该点到原点的距离)。 在二维和三维空间中的欧氏距离就是两点之间的实际距离。 计算公式&#xff1a; dist(A,B)∑i1n(Ai−Bi)2dist(A,B)\sqr…

DIN35电压电流转频率单位脉冲输出信号变换器集电极开路隔离变送器

主要特性 将直流电压或电流信号转换成单位脉冲信号。 精度等级&#xff1a;0.1 级、0.2 级。产品出厂前已检验校正&#xff0c;用户可以直接使用。 国际标准信号输入:0-5V/0-10V/1-5V 等电压信号,0-10mA/0-20mA/4-20mA 等电流信号。 输出标准信号&#xff1a;0-5KHz/0-…

MySQL 索引常见问题汇总,一次性梳理

hello&#xff0c;大家好&#xff0c;我是张张&#xff0c;「架构精进之路」公号作者。 提到MySQL查询分析&#xff0c;就会涉及到索引相关知识&#xff0c;要想学好MySQL&#xff0c;索引是重要且不得不啃下的一环&#xff0c;今天就把MySQL索引常见问题进行汇总&#xff0c;一…

vue.js实现带表情评论功能前后端实现 (滚动加载效果)

学习链接 vue.js实现带表情评论功能前后端实现&#xff08;仿B站评论&#xff09; 实现在vue项目中通过滚动条来滑动加载数据 IntersectionObserver与无限滚动加载 效果图 每次加载2条数据 思路 要实现滚动加载&#xff0c;就是当滚动条滚动到底部的时候&#xff0c;再去请…