文章目录
- 一、自动化测试介绍
-
- 1. 概念
- (1)单元测试
- (2)接口测试
- (3)UI测试
- 2. 为什么要进行自动化测试
- 二、驱动
-
- 1. 概念
- 2. 本质
- 三、selenium
-
- 1. 为什么选择selenium作为我们的web自动化工具
- 2. 环境部署
- 四、 webdriver API
-
- 1. 元素定位
-
- 一个简单的自动化示例
- (1)id
- (2)name
- (3)class name 和 tag name
- (4)CSS
- (5)XPath
- (4)link text
- (5)partial link text
- 2. 操作测试对象
-
- (1)鼠标点击和键盘输入
- (2)submit提交表单
- (3)获取元素文本和属性
- 3. 添加等待
-
- (1)sleep休眠
- (2)隐式等待
- (3)显式等待
- 注意
- 4. 信息打印
-
- (1)title打印
- (2)url打印
- 5. 浏览器操作
-
- (1)获取当前webDriver操作的标签页的句柄
- (2)获取浏览器所有标签页的句柄
- (3)修改webDriver操作的句柄
- (4)浏览器窗口大小的控制
- (5)浏览器页面滑动
- (6)控制一个标签页页面的前进和后退
- (7)弹窗操作(警告弹窗)
- 6. 模拟鼠标操作
- 7. 选中下拉框的选项
- 8. 文件上传
- 9. 屏幕截图
一、自动化测试介绍
1. 概念
自动化测试是指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果,将人为驱动的测试行为转化为机器执行的过程
自动化测试包括UI自动化、接口自动化、单元测试自动化。按照这个金字塔模型来进行自动化测试规划,可以产生最佳的自动化测试产出投入比,可以用较少的投入获得很好的收益
(1)单元测试
最大的投入应该在单元测试上,单元测试运行的频率也更高。Java的单元测试框架就是Junit
(2)接口测试
接口测试就是API测试,相对于UI自动化API自动化更加容易实现,执行起来也更加稳定
接口自动化有以下几个特点:
- 可在产品前期,接口完成后介入
- 用例维护量小
- 适合接口变动较小,界面变动频繁的项目
常见的接口自动化测试工具:Postman
(3)UI测试
UI层的自动化测试更加贴近用户的需求和软件系统的实际业务,并且有时候不得不进行UI层的测试
UI自动化测试的特点:
- 用例维护量大
- 页面相关性强,必须后期项目页面开发完成后介入
- UI测试适合于界面变动较小的项目
UI层自动化测试框架:selenium
2. 为什么要进行自动化测试
自动化测试能够代替一部分手工测试。自动化测试能够提高测试效率。比如随着功能的增加,版本越来越多,回归测试的压力也越来越大,所以仅仅通过人工测试来回归所有的版本不现实,所以我们需要借助自动化来进行回归
二、驱动
1. 概念
首先驱动是指驱动计算机里软件的程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。对于自动化测试来说,代码可以借助驱动协助打开浏览器,不需要人为的帮助
2. 本质
浏览器驱动就是一个服务器,我们通过代码向驱动发送操作浏览器的请求,驱动进行解析并执行,最后将结果返回给我们。说它是一个服务器最直接的证据就是它占用了9515端口号
三、selenium
1. 为什么选择selenium作为我们的web自动化工具
- 开源免费
- 支持多浏览器
- 支持多系统
- 支持多语言
- selenium包底层有很多可使用的API
2. 环境部署
- selenium工具包
- Chrome浏览器
- Chromedriver谷歌驱动
- jdk8
四、 webdriver API
1. 元素定位
一个简单的自动化示例
/*** 创建驱动对象并返回* @param url 驱动里的地址* @return*/
private static ChromeDriver getDriver(String url) {ChromeDriver driver = new ChromeDriver();driver.get(url);return driver;
}/*** 退出浏览器* @param driver*/
private static void closeDriver(ChromeDriver driver) {driver.quit();
}public static void test() throws InterruptedException {Thread.sleep(2000);// 输入百度网址ChromeDriver driver = getDriver("https://www.baidu.com");Thread.sleep(2000);// 找到百度输入框并输入“胡歌”driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");Thread.sleep(2000);// 找到百度一下按钮,并点击driver.findElement(By.xpath("//*[@id=\"su\"]")).click();Thread.sleep(2000);// 释放驱动对象/关闭浏览器closeDriver(driver);
}
(1)id
id是页面元素的属性,我们最常用元素定位方式,但是不是所有的元素都有id的。id只能使用一次,如果某一个元素有id属性,那么我们就能通过id来唯一的定位这个元素。例如百度首页输入框的id就是"kw"
(2)name
如果这个元素有name,并且元素的name命名在整个页面是唯一的,那么我们可以用name来定位这个元素。例如百度首页输入框的name就是"wd",并且是唯一的
(3)class name 和 tag name
tag name(标签名)
和 class name
也是定位元素的两种方式,如果那个标签或者类在页面中只使用了一次,那么我们就可以使用这两种方式来唯一的定位元素,但是并不常用,因为还需要我们对唯一性进行判断。例如百度首页输入框的class=“s_ipt”,标签名是"input"(但是百度首页有多个input标签)
(4)CSS
CSS(Cascading Style Sheets)是一种语言,它被用来描述 HTML 和 XML 文档的表现
CSS比较灵活,可以选择控件的任意属性,比如id属性,在百度首页要选中输入框也可以这样写:driver.findElement(By.cssSelector("#kw"))
CSS的获取可以用chrome的F12开发者模式中Element-右键-copy-copy selector来获取
(5)XPath
XPath 是一种在XML文档中定位元素的语言。因为HTML 可以看做XML的一种实现,所以selenium用户可以使用这种语言在web应用中定位元素
Xpath的获取可以用chrome的F12开发者模式中Element-右键-copy-copy xpath来获取
需要注意的是,Xpath在一个页面也会有重复的情况,并不是一个Xpath在一个页面就是唯一存在的
(4)link text
有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过链接内容,也就是 link text 来定位。需要注意的是链接内容必须这个页面唯一,否则会报错。比如百度首页左上角的"新闻"等文字链接,就可以通过link text来定位
(5)partial link text
通过部分链接定位,这个有时候也会用到
2. 操作测试对象
上述的API都是定位元素的方法,但是定位元素只是操作的第一步,之后我们要对这个元素进行操作
(1)鼠标点击和键盘输入
click
,用于点击,但是不局限于按钮,一个页面所有位置都能点击sendKeys
,键盘输入内容clear
,清除元素中输入的文本内容
代码示例:
public static void test5() throws InterruptedException {Thread.sleep(2000);ChromeDriver driver = getDriver("https://www.baidu.com");Thread.sleep(2000);// 在输入框中输入内容driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");Thread.sleep(2000);// 点击按钮driver.findElement(By.xpath("//*[@id=\"su\"]")).click();Thread.sleep(2000);// 清除内容driver.findElement(By.cssSelector("#kw")).clear();Thread.sleep(2000);closeDriver(driver);
}
(2)submit提交表单
一般来说,submit
和click
效果几乎相同,但是不同的是,submit
只能点击按钮用于提交表单,无法点击其他地方。因此我们说,提交有的功能点击都有,所以建议直接用click()
(3)获取元素文本和属性
getText
是用来获得标签之间的文本内容,而由于单标签只有一个标签,因此也就无法获取文本内容;getAttribute
用来获得元素的属性
代码示例:
public static void test6() throws InterruptedException {Thread.sleep(2000);ChromeDriver driver = getDriver("https://www.baidu.com");Thread.sleep(2000);// 获取输入框元素属性String textAttribute = driver.findElement(By.cssSelector("#kw")).getAttribute("class");System.out.println(textAttribute);driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");Thread.sleep(2000);// 获取胡歌人物介绍:"中国内地影视男演员流行乐歌手"String text = driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div:nth-child(2)")).getText();System.out.println(text);Thread.sleep(2000);closeDriver(driver);
}
3. 添加等待
等待的意义:我们在做web网站自动化测试的过程中,代码的执行速度比较快,而前端页面渲染的速度相对较慢,那么有可能我们进行元素定位时页面的元素还没加载完成,此时对元素进行定位就会出现异常,降低自动化脚本的稳定性和测试效率
(1)sleep休眠
sleep休眠就是通过Thread.sleep(毫秒)来进行定时休眠
- 优点:语法简单,适合调试的时候用
- 缺点:需要等待固定的时间,造成测试时间的大量消耗,大大降低了自动化测试的效率
(2)隐式等待
隐式等待不同于sleep休眠,隐式等待是在页面加载完毕或者等待时间超过设置的最长等待时间的情况下结束等待,如果超出等待时间,就会抛出异常
- 特点:隐式等待是作用于webDriver的整个生命周期,它并不需要知道用户要查询哪个元素
- 优点:节省大量的等待时间,元素展现后可以直接执行下一步,执行效率高
- 缺点:需要等待页面所有元素都展现才会执行下一步,仍然会有额外的时间浪费
代码示例:
public static void test7() {ChromeDriver driver = getDriver("https://www.baidu.com");// 设置隐式等待的最长等待时间为2sdriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");driver.findElement(By.cssSelector("#su")).click();// 获取胡歌人物介绍:"中国内地影视男演员流行乐歌手"String text = driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div:nth-child(2)")).getText();System.out.println(text);closeDriver(driver);
}
(3)显式等待
显式等待和隐式等待类似,但是它是针对某一个元素进行等待,在固定的时间范围内频繁的轮询元素是否存在
- 优点:可以针对某一个元素来进行等待,不需要等待整个页面渲染完成,极大降低了自动化整体的等待时间
- 缺点:写法更加复杂
代码示例:
public static void test8() {ChromeDriver driver = getDriver("https://www.baidu.com");driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");driver.findElement(By.cssSelector("#su")).click();// 第一个参数是WebDriver对象// 第二个参数是Duration类方法,用于设置强制等待的最长时间WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));// ExpectedConditions类提供了很多方法可以用来测试// presenceOfElementLocated返回当前页面的web元素,即查看我们指定的元素是否存在wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div:nth-child(2)")));// 获取胡歌人物介绍:"中国内地影视男演员流行乐歌手"String text = driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div:nth-child(2)")).getText();System.out.println(text);// 检查页面元素对应的文本信息是否正确wait.until(ExpectedConditions.textToBe(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > a > div > p > span > span"), "胡歌"));closeDriver(driver);
}
补充:ExpectedConditions类提供了很多方法可以用来测试,例如presenceOfElementLocated,检查页面是否存在对应的元素;textToBe,检查页面元素对应的文本信息是否正确
注意
- 隐式等待和显式等待都检测不到弹窗的加载,因此如果对弹窗的信息进行操作,必须加入强制等待
- 隐式等待和显式等待不建议一起使用,会产生意想不到的效果,每次等待的时间也是不确定的
4. 信息打印
(1)title打印
将webDriver控制的当前标签页的页面的title打印出来。言外之意,就是如果新打开了一个标签页,webDriver仍然打印的是原来标签页的title,这里注意浏览器标签页和页面的区别
(2)url打印
打印当前webDriver驱动对象控制的标签页的url。这里需要注意的和title打印需要注意的一样
代码示例:
public static void test9() {ChromeDriver driver = getDriver("https://www.baidu.com");System.out.println(driver.getTitle());System.out.println(driver.getCurrentUrl());closeDriver(driver);
}
5. 浏览器操作
上述webDriver以一个标签页为单位进行操作,实际是selenium为每一个标签页设置了唯一标识,称之为句柄,如果我们想操作新打开的标签页,就必须明确修改webDriver的句柄(注意,句柄是实时生成的,每次测试时句柄都不一样)
(1)获取当前webDriver操作的标签页的句柄
driver.getWindowHandle() // 返回值是字符串类型
(2)获取浏览器所有标签页的句柄
driver.getWindowHandles() // 返回值是Set<String>类型
(3)修改webDriver操作的句柄
跳转到最新的标签页,最简单粗暴的做法就是维护两个Set,一个保存旧的所有句柄,一个保存新的所有句柄,通过遍历新的Set,在旧的Set里找是否存在,如果不存在,那么该句柄所对应的标签页就是新打开的标签页。个人建议,善用driver的close操作,保证测试的整个过程中浏览器最多只有两个标签页,然后我们就不需要维护两个Set,就可以实现句柄的快速切换,因为我们进行测试的时候,最多就是点击原标签页的某个链接打开了另一个标签页,验证两个页面之间的关系,不会说一下打开两个新页面的情况,因此完全可以只保存当前标签页和新标签页的句柄
如果真的打开标签页很多又想要跳转到指定的标签页,建议是在刚打开那个标签页的时候就对它的句柄进行保存
代码示例:
public static void test10() throws InterruptedException {ChromeDriver driver = getDriver("https://www.baidu.com");// 设置隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));// 点击百度首页的新闻链接driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();Thread.sleep(3000);// 获取当前标签页的句柄String handle = driver.getWindowHandle();System.out.println("当前句柄:" + handle);// 关闭当前driver操作的标签页driver.close();Thread.sleep(3000);System.out.println("==================");// 获取所有标签页的句柄Set<String> handles = driver.getWindowHandles();for (String str: handles) {// 切换 WebDriver 控制的句柄if(!str.equals(handle)) {driver.switchTo().window(str);}System.out.println(str);}System.out.println("当前句柄:" + driver.getWindowHandle());closeDriver(driver);
}
(4)浏览器窗口大小的控制
- 窗口最大化
driver.manage.window().maxmize();
- 窗口最小化
driver.manage.window().minmize();
- 设置窗口尺寸
driver.manage.window().setSize(new Dimension(宽度,高度));(单位是像素)
代码示例:
public static void test11() throws InterruptedException {ChromeDriver driver = getDriver("https://www.baidu.com");Thread.sleep(2000);// 窗口最大化driver.manage().window().maximize();Thread.sleep(2000);// 窗口最小化driver.manage().window().minimize();Thread.sleep(2000);// 设置窗口尺寸,参数是一个Dimension对象,这个对象的构造方法的参数分别是宽度,高度driver.manage().window().setSize(new Dimension(1200, 600));Thread.sleep(2000);closeDriver(driver);
}
(5)浏览器页面滑动
WebDriver本身是无法控制页面滑动的,但是它可以通过方法执行js语句来实现页面滑动
- 滑动到底部
String js1 = "window.scrollTo(0, document.body.scrollHeight)"; // WebDriver通过关于执行js语言的字符串来实现窗口滑动 driver.executeScript(js1);
- 滑动到顶部
String js2 = "window.scrollTo(0, 0)"; driver.executeScript(js2);
代码示例:
public static void test12() throws InterruptedException {ChromeDriver driver = getDriver("https://www.baidu.com");// 点击新闻链接并将driver的句柄切换到新闻标签页driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();String handle = driver.getWindowHandle();Set<String> handles = driver.getWindowHandles();for (String str: handles) {if(!str.equals(handle)) {driver.switchTo().window(str);break;}}Thread.sleep(2000);// 将窗口滑动到底部// 但是如果页面不完全是由html写成,那么可能就无法滑动到最下面String js1 = "window.scrollTo(0, document.body.scrollHeight)";// WebDriver通过关于执行js语言的字符串来实现窗口滑动driver.executeScript(js1);Thread.sleep(4000);// 再写一遍是为了测试是否能够通过多次滑动将页面滑到底部// 实验发现百度新闻页并不是一次性加载完成,而是随着滑动而加载// 因此我们才无法一次将它滑动到底部driver.executeScript(js1);Thread.sleep(4000);driver.executeScript(js1);Thread.sleep(4000);driver.executeScript(js1);Thread.sleep(4000);// 将窗口滑动到顶部String js2 = "window.scrollTo(0, 0)";driver.executeScript(js2);Thread.sleep(2000);closeDriver(driver);
}
(6)控制一个标签页页面的前进和后退
注意,前进和后退操作都是针对当前标签页的,如果打开了新的标签页,除非通过修改WebDriver保存的句柄,否则新标签页将无法操作
- 前进
driver.navigate().forward()
- 后退
driver.navigate().back()
代码示例:
public static void test13() throws InterruptedException {ChromeDriver driver = getDriver("https://www.baidu.com");driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");driver.findElement(By.xpath("//*[@id=\"su\"]")).click();Thread.sleep(2000);// 后退driver.navigate().back();Thread.sleep(2000);// 前进driver.navigate().forward();Thread.sleep(2000);closeDriver(driver);
}
(7)弹窗操作(警告弹窗)
我们在前端代码里能定位到的普通弹窗都可以使用driver.findElement()方法来定位元素,但是有的弹窗我们无法定位到,就需要借助WebDriver的特殊接口,比如alert的警告弹窗,我们需要通过使用Selenium中提供的alert接口来处理
Alert alert = driver.switchTo().alert();
// 点击确认按钮
alert.accept();
// 点击取消按钮
alert.dismiss();
// 往弹窗的输入框输入信息
alert.sendKeys("hello");
代码示例:
public static void test14() throws InterruptedException {ChromeDriver driver = getDriver("file:///D:/study/%E6%AF%94%E7%89%B9/gitee%E4%B8%8A%E4%BC%A0%E4%BB%A3%E7%A0%81/javaweb_study/H-20230106/test2.html");Thread.sleep(2000);// 点击按钮,触发警告框driver.findElement(By.cssSelector("body > form > input[type=button]:nth-child(14)")).click();Thread.sleep(2000);// 点击警告框Alert alert = driver.switchTo().alert();// 点击确认按钮alert.accept();// 点击取消按钮alert.dismiss();// 往弹窗的输入框输入信息alert.sendKeys("hello");Thread.sleep(2000);closeDriver(driver);
}
6. 模拟鼠标操作
点击操作我们虽然可以通过click()实现,但是我们无法直观的看到点击操作,只能通过数据改变或者页面跳转来看到效果。selenium提供了Actions接口,我们就可以通过设置,直观的看到某个元素被选中
WebElement ele = driver.findElement(元素标识);
Actions actions = new Actions(driver);
// clickAndHold()参数必不可少,该方法表示鼠标移动到指定元素并保持
// perform表示演示
actions.clickAndHold(ele).perform();
// 该方法表示鼠标移动到元素并点击
actions.click(ele).perform();
代码示例:
public static void test15() throws InterruptedException {ChromeDriver driver = getDriver("https://www.baidu.com");driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");driver.findElement(By.cssSelector("#su")).click();WebElement ele = driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > a > div > p > span > span"));Actions actions = new Actions(driver);actions.clickAndHold(ele).perform();Thread.sleep(2000);actions.click(ele).perform();Thread.sleep(2000);closeDriver(driver);
}
7. 选中下拉框的选项
关于下拉框,我们是可以通过click进行选择的,但是可能有些麻烦,因此Selenium提供了接口Select,通过Select来选择下拉框的选项
WebElement ele = driver.findElement(By.cssSelector("body > form > select"));
Select select = new Select(ele);
// 索引从0开始递增
select.selectByIndex(0);
// 通过元素的value属性选择
select.selectByValue("计算机网络");
// 通过可见到的文本进行选择
select.selectByVisibleText("计算机网络");
//
代码示例:
public static void test16() throws InterruptedException {ChromeDriver driver = getDriver("file:///D:/study/%E6%AF%94%E7%89%B9/gitee%E4%B8%8A%E4%BC%A0%E4%BB%A3%E7%A0%81/javaweb_study/H-20230106/test2.html");Thread.sleep(2000);WebElement ele = driver.findElement(By.cssSelector("body > form > select"));Select select = new Select(ele);select.selectByIndex(0);Thread.sleep(2000);closeDriver(driver);
}
8. 文件上传
由于驱动只能控制浏览器的操作,但是文件在本地,因此我们就需要想个其他的方法,通过sendKeys(文件路径)来实现上传本地文件
代码示例:
public static void test17() throws InterruptedException {ChromeDriver driver = getDriver("file:///D:/study/%E6%AF%94%E7%89%B9/gitee%E4%B8%8A%E4%BC%A0%E4%BB%A3%E7%A0%81/javaweb_study/H-20230106/test2.html");// 点击上传文件按钮,并输入要输入文件的文件路径+文件名driver.findElement(By.cssSelector("body > form > input[type=file]:nth-child(16)")).sendKeys("C:\\Users\\DELL\\Desktop\\面试复习计划.png");Thread.sleep(2000);closeDriver(driver);
}
9. 屏幕截图
由于代码执行速度比页面渲染的速度要快,因此我们有时报错不是因为代码问题,而是因为速度问题,但是这种问题如果不是提前知道,就很难想到,也很难定位问题,因此我们就可以通过截图来留证,通过查看对每个页面进行测试时的屏幕截图,就能更容易的定位问题
语法:
// 截图后产生的文件,创建截图文件对象
File srcFile = driver.getScreenshotAs(OutputType.FILE);
// 将截图文件保存到我们指定路径下
File fileName = new File("./src/test/java/screenshot/test1.png");
// 将截图文件保存到指定路径下
FileUtils.copyFile(srcFile, fileName);
代码示例:
public static void test18() throws IOException {ChromeDriver driver = getDriver("https://www.baidu.com");// 设置隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));driver.findElement(By.cssSelector("#kw")).sendKeys("胡歌");driver.findElement(By.cssSelector("#su")).click();// 截图后产生的文件,创建截图文件对象File srcFile = driver.getScreenshotAs(OutputType.FILE);// 将截图文件保存到我们指定路径下File fileName = new File("./src/test/java/screenshot/test1.png");// 将截图文件保存到指定路径下FileUtils.copyFile(srcFile, fileName);driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div:nth-child(2) > span:nth-child(1)"));File srcFile2 = driver.getScreenshotAs(OutputType.FILE);File fileName2 = new File("./src/test/java/screenshot/test2.png");FileUtils.copyFile(srcFile2, fileName2);closeDriver(driver);
}
查看全文
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/2217711.html
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!
相关文章:
selenium-基于UI的自动化测试框架
文章目录一、自动化测试介绍1. 概念(1)单元测试(2)接口测试(3)UI测试2. 为什么要进行自动化测试二、驱动1. 概念2. 本质三、selenium1. 为什么选择selenium作为我们的web自动化工具2. 环境部署四、 webdriv……
零散记录1
对字典进行排序
(1)升序:
d{"a":1,"d":4,"c":3,"b":2}
print(sorted(d.items()))
或采用下面操作
d{"a":1,"b":2,"c":3}for k in sorted(d.keys(),reverseTrue):……
华为OD机试题【狼羊过河 or 羊、狼、农夫过河】用 C++ 编码,速通
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:狼羊过河 or 羊、狼、农夫过河……
算法套路七——二叉树递归
算法套路七——二叉树递归
如何思考二叉树相关问题? 不要一开始就陷入细节,而是思考整棵树与其左右子树的关系。为什么需要使用递归? 子问题和原问题是相似的,他们执行的代码也是相同的(类比循环)……
代码随想录训练营第49天|121.买卖股票的最佳时机、122.买卖股票的最佳时机Ⅱ
121.买卖股票的最佳时机、122.买卖股票的最佳时机Ⅱ
121.买卖股票的最佳时机
显然这道题可以用普通的方法做,可能会更容易想,也更容易做,但是由于在学习动态规划,因此此文只给动态规划的解法。 对于每一天的状况,我们……
你还在用原生 poi 处理 excel?太麻烦了来瞧瞧这个
1、easypoi
前言
Excel 在日常工作中经常被用来存储用例信息,是一种非常便捷的数据存储工具有着众多的优点,我们就不一一介绍了。
今天来讲讲 Java 操作 Excel,总所周知 Java 是世界上最好的语言(不容反驳)ÿ……
【python日期/时间题】
time及datetime函数应用
格式修改
a "2013-10-10 23:40:00"想改为 a "2013/10/10 23:40:00"
import time
a "2013-10-10 23:40:00"
b time.strptime(a, "%Y-%m-%d %H:%M:%S")
c time.strftime("%Y/%m/%d %H:%M:%S"……
【多核异构】i.MX8M Plus开发板的M核SPI主从模式通讯——飞凌嵌入式
SPI(串行外围设备接口)是一种低成本、易使用的接口协议,具备全双工、高速、通讯简单的特点,被广泛应用于微控制器和外围设备芯片之间的通讯。当SPI接口作为主模式时可以连接Flash存储器、AD采样芯片、实时时钟RTC、LCD显示屏、音频……
Gin的笔记
1 创建一个gin项目
配置 GoSDK的 root
1.1 创建项目目录
直接创建一个文件夹使用GoLand打开
1.2 生成mod文件
终端执行
go mod init 项目名称1.3 安装gin的相关包
配置代理 setting – go – module
GOPROXYhttps://goproxy.cn,direct安装gin相关包
终端执行命令
go g……
23、ts中的函数,ts对函数进行约束,可选参数,参数默认值, 剩余参数,函数重载
函数非为声明式和表达式
声明式:
function sum(x, y) {return x y
}函数表达式
let mySum function(x, y) {return x y
}ts对函数进行约束
1、 函数有输入和输出,所以对输入和输出都已经进行约束 2、参数多余或者少于既定参数,都是会发……
【Java开发】设计模式 12:解释器模式
1 解释器模式介绍
解释器模式是一种行为型设计模式,它提供了一种方法来解释语言、表达式或符号。
在该模式中,定义了一个表达式接口,并实现了对应的表达式类,这些类可以解释不同的符号组成的表达式,从而实现对语言的……
反序列化渗透与攻防(五)之shiro反序列化漏洞
Shiro反序列化漏洞
Shiro介绍
Apache Shiro是一款开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默……
vue2+vue3
vue2vue3尚硅谷vue2vue2 课程简介【02:24】vue2 Vue简介【17:59】vue2 Vue官网使用指南【14:07】vue2 搭建Vue开发环境【13:54】vue2 Hello小案例【22:25】了解: 不常用常用:id 更常用 简单class差值总结vue 实例vue 模板 : 先 取 ࿰……
【hello Linux】环境变量
目录 1. 环境变量的概念 2. 常见的环境变量 3. 查看环境变量 4. 和环境变量相关的命令 5. 环境变量的组织方式 6. 通过代码获取环境变量 7. 通过系统调用获取环境变量 Linux🌷 在开始今天的内容之前,先来看一幅图片吧! 不知道你们是否和我一……
【Linux基础】常用命令整理
ls命令
-a选项,可以展示隐藏的文件和文件夹-l选项,以列表形式展示内容-h,需要和-l搭配使用,可以展示文件的大小单位ls -lah等同于la -a -l -h
cd命令(change directory)
语法:cd [Linux路径]……
客快物流大数据项目(一百一十二):初识Spring Cloud
文章目录
初识Spring Cloud
一、Spring Cloud简介
二、SpringCloud 基础架构图…
C和C++中的struct有什么区别
区别一: C语言中: Struct是用户自定义数据类型(UDT)。 C语言中: Struct是抽象数据类型(ADT),支持成员函数的定义。
区别二:
C中的struct是没有权限设置的,……
docker的数据卷详解
数据卷 数据卷是宿主机中的一个目录或文件,当容器目录和数据卷目录绑定后,对方修改会立即同步
一个数据卷可以同时被多个容器同时挂载,一个容器也可以被挂载多个数据卷
数据卷作用:容器数据持久化 /外部机器和容器间接通信 /容器……
13、Qt生成dll-QLibrary方式使用
Qt创建dll,使用QLibrary类方式调用dll
一、创建项目
1、新建项目->其他项目->Empty qmake Project->Choose 2、输入项目名,选择项目位置,下一步 3、选择MinGW,下一步 4、完成 5、.pro中添加TEMPLATE subdirsÿ……
基于mapreduce 的 minHash 矩阵压缩
Minhash作用: 对大矩阵进行降维处理,在进行计算俩个用户之间的相似度。
比如: 俩个用户手机下载的APP的相似度,在一个矩阵中会有很多很多的用户要比较没俩个用户之间的相似度是一个很大的计算任务 如果首先对这个矩阵降维处理&am……
编程日记2023/4/16 14:50:37