JAVA自动化之Junit单元测试框架详解

一、JUnit概述&配置

1、Junit是什么?

Junit是一个Java 编程语言的开源测试框架,用于编写和运行测试。官网 地址:https://junit.org/junit4/

2、Maven配置

?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>junit</groupId><artifactId>junitTest</artifactId><version>0.0.1-SNAPSHOT</version><packaging>pom</packaging><!-- https://mvnrepository.com/artifact/junit/junit --><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
</project>

二、Assertions 断言

JUnit提供了一些辅助的函数,用来判断被测试的方法是否如我们预期的效果一样正常执行。这些辅助函数被称之为断言。
常用断言:

方法示例功能
assertArrayEqualsassertArrayEquals("message", expected, actual);判断两个数组是否相等
assertEqualsassertEquals("message", "text", "text");判断两个对象是否相等
assertFalseassertFalse("failure - should be false", false);判断表达式是否为false
testAssertTrueassertTrue("failure - should be true", true);判断表达式是否为true
assertNotNullassertNotNull("should not be null", new Object());判断是否非空
assertNullassertNull("should be null", null);判断是否为空
assertNotSameassertNotSame("should not be same Object", new Object(), new Object());判断是否为不同对象
assertSameassertSame("should be same", aNumber, aNumber);判断是否为同一对象
..................

三、Test Runners 测试运行器

JUnit中所有的测试方法都是由测试运行器负责执行。当一个类被@RunWith注释或拓展了一个@RunWith注释的类,JUnit将会使用引用的类来执行测试,而不是使用JUnit内置的运行器。

  org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);

 Specialized Runners:
Suite:Suite是一个标准的运行器,允许手动构建包含来自许多类的测试集。
Parameterized:Parameterized是一个实现参数化测试的标准运行器。运行参数化测试类时,测试方法和测试数据进行合并来创建测试实例。
Categories:Categories运行器来制定分类,定义测试被包含或排除。

四、Aggregating tests in suites 套件

测试套件用于捆绑几个单元测试用例并且一起执行他们,使用@RunWith 和 @Suite 注解。

@RunWith(Suite.class)
@Suite.SuiteClasses({AssertTests.class, CalculatorTest.class})
public class SuiteTest {// the class remains empty, used only as a holder for the above annotations
}

五、Test execution order 执行顺序

要改变测试执行的顺序只需要在测试类上使用 @FixMethodOrder注解,并指定一个可用的MethodSorter即可:
@FixMethodOrder(MethodSorters.DEFAULT):JUnit默认使用一个确定的,但不可预测的顺序
@FixMethodOrder(MethodSorters.JVM): 保留测试方法的执行顺序为JVM返回的顺序,每次测试的执行顺序有可能会所不同
@FixMethodOrder(MethodSorters.NAME_ASCENDING):根据测试方法的方法名排序,按照词典排序规则(ASC从小到大递增)

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ExecutionOrderTest {@Testpublic void testB() {System.out.println("second");}@Testpublic void testA() {System.out.println("first");}@Testpublic void testC() {System.out.println("third");}
}

运行结果:

first
second
third

六、Expected Exceptions 异常测试

用于测试某一方法是否抛出了正确的异常。

1、@Test(expected=xxx)方式:当抛出的异常与expected参数指定的异常相同时,测试通过。
2、try...fail...catch...方式:捕捉具体待测语句的异常信息并断言,当没有异常被抛出的时候fail方法会被调用,输出测试失败的信息。
3、ExpectedException Rule方式:使用Rule标记来指定一个ExpectedException,并在测试相应操作之前指定期望的Exception类型。

public class ExpectedExceptionsTest {//方法一:@Test(expected=xxx)@Test(expected = IndexOutOfBoundsException.class)public void empty() {new ArrayList<Object>().get(0);}//方法二:try...fail...catch...  当没有异常被抛出的时候fail方法会被调用,输出测试失败的信息。@Testpublic void testExceptionMessage() {try {new ArrayList<Object>().get(0);fail("Expected an IndexOutOfBoundsException to be thrown");} catch (IndexOutOfBoundsException anIndexOutOfBoundsException) {assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0"));}}//方法三:在测试之前使用Rule标记来指定一个ExpectedException,并在测试相应操作之前指定期望的Exception类型(如IndexOutOfBoundException.class)@Rulepublic ExpectedException thrown = ExpectedException.none();@Testpublic void shouldTestExceptionMessage() throws IndexOutOfBoundsException {List<Object> list = new ArrayList<Object>();thrown.expect(IndexOutOfBoundsException.class);thrown.expectMessage("Index: 0, Size: 0");list.get(0);}
}

七、Matchers and assertThat

JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活。并且使用全新的断言语法assertThat,结合Hamcrest提供的匹配符,只用这一个方法,就可以实现所有的测试。
assertThat语法:
assertThat(T actual, Matcher matcher);
assertThat(String reason, T actual, Matcher matcher);
其中reason为断言失败时的输出信息,actual为断言的值或对象,matcher为断言的匹配器,里面的逻辑决定了给定的actual对象满不满足断言。
Matchers详见:
http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html

八、Ignoring tests 忽略测试

  • 方法用 @Ignore 注解了将不会被执行
  • 类用 @Ignore 注解后,其下所有测试方法将不会被执行
public class IgnoreTest {@Ignore("Test is ignored as a demonstration")@Testpublic void testSame() {assertThat(1, is(1));}
}

九、Timeout for tests 超时测试

@Timeout 注解用来测试特定方法的执行时间。如果测试方法的执行时间大于指定的超时参数,测试方法将抛出异常,测试结果为失败。指定的超时参数单位为毫秒
1、@Test注解上的timeout参数,作用域为方法,单位毫秒

@Test(timeout = 2000)public void testSleepForTooLong() throws Exception {log += "ran1";TimeUnit.SECONDS.sleep(100); // sleep for 100 seconds}

2、Timeout Rule,作用域为测试类

public class TimeoutTests {public static String log;private final CountDownLatch latch = new CountDownLatch(1);@Rulepublic Timeout globalTimeout = Timeout.seconds(3); // 3 seconds max per method tested@Testpublic void testSleepForTooLong() throws Exception {log += "ran1";TimeUnit.SECONDS.sleep(100); // sleep for 100 seconds}@Testpublic void testBlockForever() throws Exception {log += "ran2";latch.await(); // will block}
}

十、Parameterized tests 参数化测试

参数化测试允许开发人员使用不同的值反复运行同一个测试。创建参数化测试步骤:

  • 用 @RunWith(Parameterized.class) 来注释 test 类。
  • 创建一个由 @Parameters 注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。
  • 创建一个公共的构造函数,接受测试数据。
  • 为每一列测试数据创建一个实例变量。
  • 用实例变量作为测试数据的来源来创建测试用例。

1、Constructor方式
 

@RunWith(Parameterized.class)
public class FibonacciTest {@Parameters(name = "{index}: fib({0})={1}")public static Collection<Object[]> data() {return Arrays.asList(new Object[][] {{ 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }});}private int fInput;private int fExpected;public FibonacciTest(int input, int expected) {this.fInput = input;this.fExpected = expected;}@Testpublic void test() {assertEquals(fExpected, Fibonacci.compute(fInput));}
}

2、Field injection方式

@RunWith(Parameterized.class)
public class FibonacciTest {@Parameters(name = "{index}: fib({0})={1}")public static Collection<Object[]> data() {return Arrays.asList(new Object[][] {{ 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }});}@Parameter // first data value (0) is defaultpublic /* NOT private */ int fInput;@Parameter(1)public /* NOT private */ int fExpected;@Testpublic void test() {assertEquals(fExpected, Fibonacci.compute(fInput));}
}

十一、Assumptions with assume 假定测试

使用Assumptions类中的假设方法时,当假设不成立时会报错,但是测试会显示被ignore忽略执行。也就是当一个类中有多个测试方法时,其中一个假设测试方法假设失败,其他的测试方法全部成功,那么该测试类也会显示测试成功。
假设方法适用于:在不影响测试是否成功的结果的情况下根据不同情况执行相关代码。

public class AssumptionsTest {@Testpublic void testAssumTrue() {System.out.println("test");assumeTrue(3>5);//该方法中下面所有的代码在上面假设的条件成立后执行//如果上述假设不成立,则会忽略执行该行下面的代码,并报错System.out.println("assume is true!");}@Testpublic void testAssumFalse(){assumeFalse(3>5);System.out.println("assume is true!");}}

 以下语法JUnit5支持:

@Testpublic void testAssumTrueMessage() {assumeTrue(3<5,//第二个参数为当第一个参数不成立时,输出的自定义错误信息() -> "Aborting test: not on developer workstation");System.out.println("assume is true!");}@Testpublic void testAssumeTrueLambda(){//这个方法的第一个参数为函数式接口,无参数返回值为booleanassumeTrue(()->{System.out.println("in assumeTrue");boolean flag = false;return flag;});System.out.println("out assumeTrue");}@Testpublic void testAssumThat() {assumingThat(3>5,() -> {//与上述方法不同的是,仅当前面假设成立时,才会执行这里面的语句//且只会影响到该lambda表达式中的代码assertEquals(2, 2);});//此处的断言不受上述assumingThat限制,在所有情况下都会执行System.out.println("no effect");assertEquals("a string", "a string");}

十二、Rules 规则

一个JUnit Rule就是一个实现了TestRule的类,用来在每个测试方法的执行前后执行一些代码。
1、框架自带的Rule
JUnit自带很多已经实现过好了的JUnit Rule,比如Timeout,ExpectedException等等。

2、自定义Rule
自定义一个Rule就是implement一个TestRule interface,实现一个叫apply()的方法。
例:在测试方法运行之前,记录测试方法所在的类名和方法名,然后在测试方法运行之后打印出来。

public class MethodNameExample implements TestRule {@Overridepublic Statement apply(final Statement base, final Description description) {return new Statement() {@Overridepublic void evaluate() throws Throwable {//base.evaluate()之前为测试方法运行之前所做操作String className = description.getClassName();String methodName = description.getMethodName();//运行测试方法base.evaluate();//base.evaluate()之后为测试方法运行之后所做操作System.out.println("Class name: "+className +", method name: "+methodName);}};}
}

public class RuleTest2 {@Rulepublic MethodNameExample methodNameExample = new MethodNameExample();@Testpublic void addition_isCorrect() throws Exception {assertEquals(4, 2 + 2);}@Testpublic void mulitiplication_isCorrect() throws Exception {assertEquals(4, 2 * 2);}
}

十三、Theories

在参数化测试中,我们需要给定所有具体的测试数据组。而在Theories测试中,用户只需给定了一些数据,JUnit自动利用这些数据组合出各种各种可能的组合来执行测试。

1、内置实现

(1)@DataPoints注解静态变量方式

@RunWith(Theories.class)
public class TheoryTest {//允许的最大误差private static final double DELTA = 0.01;/*@DataPoints注解静态变量*/@DataPointpublic static int ZERO = 0;@DataPointpublic static int TWO = 2;@DataPointpublic static int EIGHT = 8;//标志这个测试为Theory测试@Theorypublic void testDivide(int dividend, int divisor) {//跳过除数为0的caseassumeThat(divisor, not(0));//Calculator.divide(dividend, divisor)方法返回他们相除的结果assertEquals(dividend / divisor, Calculator.divide(dividend, divisor), DELTA);System.out.println("Passed with: dividend=" + dividend + ", divisor=" + divisor);}
}

(2)@DataPoints注解静态方法方式

@RunWith(Theories.class)
public class TheoryTest {//允许的最大误差private static final double DELTA = 0.01;/*@DataPoints注解一个静态方法*/@DataPointspublic static int[] getTestData() {return new int[]{0, 2, 8};}//标志这个测试为Theory测试@Theorypublic void testDivide(int dividend, int divisor) {//跳过除数为0的caseassumeThat(divisor, not(0));//Calculator.divide(dividend, divisor)方法返回他们相除的结果assertEquals(dividend / divisor, Calculator.divide(dividend, divisor), DELTA);System.out.println("Passed with: dividend=" + dividend + ", divisor=" + divisor);}
}

@DataPoint用于注解静态变量(或静态方法),表示这个变量是个数据点。当执行testDivide这个Theory测试时,JUnit会把所有的DataPoint数据两两组合,形成一组组的测试数据,并用这些数据分别执行测试。执行上面的测试会输出以下结果:

Passed with: dividend=0, divisor=2
Passed with: dividend=0, divisor=8
Passed with: dividend=2, divisor=2
Passed with: dividend=2, divisor=8
Passed with: dividend=8, divisor=2
Passed with: dividend=8, divisor=8

 (3)如果需要限定某个参数,可以使用@TestOn注解

import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.experimental.theories.suppliers.TestedOn;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
@RunWith(Theories.class)
public class TheoryTest {//允许的最大误差private static final double DELTA = 0.01;//如果需要限定某个参数,可以使用@TestOn注解@Theorypublic void testDivide2(@TestedOn(ints = {0, 2, 8}) int dividend,@TestedOn(ints = {2, 8}) int divisor) {assertEquals(dividend / divisor, Calculator.divide(dividend, divisor), DELTA);System.out.println("Passed with: dividend=" + dividend + ", divisor=" + divisor);}
}

2、自定义实现

JUnit默认只提供了一个int型的简单 Parameter Supplier 实现,而Theory机制真正的价值在于,能参考@TestedOn的做法,相对简单的完全自定义出可重用 Parameter Supplier,适应于各种复杂要求的限定范围参数值测试场景,满足开发者所需的高度动态自定义范围取值自动化测试,同时保留与一般@Test相同的强大兼容性。
例:
(1)定义annotation注解接口Between
 

@Retention(RetentionPolicy.RUNTIME)
// 声明注解接口所使用的委托处理类
@ParametersSuppliedBy(BetweenSupplier.class)
public @interface Between{// 声明所有可用参数,效果为 @Between([first = int,] last = int)int first() default 0;  // 声明默认值int last();
}

(2)定义委托处理类 BetweenSupplier

public class BetweenSupplier extends ParameterSupplier {@Overridepublic List<PotentialAssignment> getValueSources(ParameterSignature sig) {// 自定义实参值列表List<PotentialAssignment> list = new ArrayList<PotentialAssignment>();// 获取注解变量Between between = sig.getAnnotation(Between.class);// 获取通过注解@Between传入的first值int first = between.first();// 获取通过注解@Between传入的last值int last = between.last();for (int i = first; i <= last; i++) {// PotentialAssignment.forValue(String name, Object value)// name为value的描述标记,没实际作用// value为实参可选值list.add(PotentialAssignment.forValue("name", i));}return list;}
}

(3)调用方式

@RunWith(Theories.class)
public class TheoryDefinedTest {@Theorypublic final void test(@Between(last = 0) int i, @Between(first = 3, last= 10) int j) {// i 取值为 0(first默认=0,last=0),j 取值为 3-10System.out.println("i="+i+"  j="+j);}
}

(4)运行结果

i=0  j=3
i=0  j=4
i=0  j=5
i=0  j=6
i=0  j=7
i=0  j=8
i=0  j=9
i=0  j=10

十四、Test fixtures

Test Fixture是指一个测试运行所需的固定环境,也是就是测试运行之前所需的稳定的、公共的可重复的运行环境,这个“环境”不仅可以是数据,也可以指对被测软件的准备,例如实例化被测方法所依赖的类、加载数据库等等。

  • @Before - 在每个@Test方法之前运行
  • @After - 在每个@Test方法之后运行
  • @BeforeClass - 在所有的@Test方法之前运行一次
  • @AfterClass - 在所有的@Test方之后运行一次
    注:

1、如果创建一个子类继承有fixture注解的父类,那么子类中的@Before方法会在测试方法之前、父类的@Before执行之后执行。
2、如果@Before方法里抛出了异常,@Test方法会跳过,但是@After还是会执行
3、每个测试方法都会在单独的测试类的实例里面运行,@BeforeClass在测试实例创建之前执行
 

public class FixtureTest {private static int quantity = 0;public FixtureTest() {quantity++;}@BeforeClasspublic static void breforeTestOnlyOnce() throws Exception {System.out.println("Run before all test only once..."+ quantity);}@AfterClasspublic static void afterTestOnlyOnce() throws Exception {System.out.println("Run after all test only once..."+ quantity);}@Beforepublic void beforePerTest() {System.out.println("Run before per test ..."+ quantity);}@Afterpublic void afterPerTest() {System.out.println("Run after per test ..."+ quantity);}//Test Method@Testpublic void testOne() {System.out.println("testOne Start..."+ quantity);}@Testpublic void testTwo() {System.out.println("testTwo Start..."+ quantity);}
}

运行结果:

Run before all test only once...0
Run before per test ...1
testOne Start...1
Run after per test ...1
Run before per test ...2
testTwo Start...2
Run after per test ...2
Run after all test only once...2

十五、Categories 用例分类

category 和 testSuite的比较:testSuite是类级分组(xx.class),category是用例级分组(@Test),category是testSuite的升级
category使用步骤:
1、创建好测试类,及测试类中的测试用例
2、创建接口:按用例的分组来创建
3、@Category注解:将用例用@Category注解分组
4、创建类来执行这些分组的类

public interface FastTests { /* category marker */ }
public interface SlowTests { /* category marker */ }public class A {@Testpublic void a() {fail();}@Category(SlowTests.class)@Testpublic void b() {}
}@Category({SlowTests.class, FastTests.class})
public class B {@Testpublic void c() {}
}@RunWith(Categories.class)
@IncludeCategory(SlowTests.class)
@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
public class SlowTestSuite {// Will run A.b and B.c, but not A.a
}@RunWith(Categories.class)
@IncludeCategory(SlowTests.class)
@ExcludeCategory(FastTests.class)
@SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
public class SlowTestSuite {// Will run A.b, but not A.a or B.c
}

十六、总结

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

 

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取   

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大数据存储与处理】1. hadoop单机伪分布安装和集群安装

0. 写在前面 0.1 软件版本 hadoop2.10.2 ubuntu20.04 openjdk-8-jdk 0.2 hadoop介绍 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop实现了一个…

pip install open-interpreter报错,无法安装

标题pip install open-interpreter报错&#xff0c;无法安装 ERROR: Could not find a version that satisfies the requirement open-interpreter (from versions: none) ERROR: No matching distribution found for open-interpreter 另外发现自己换了很多国内镜像源&#x…

【LeetCode热题100】--54.螺旋矩阵

54.螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 按层遍历 可以将矩阵看成若干层&#xff0c;首先输出最外层的元素&#xff0c;其次输出次外层的元素&#xff0c;直到输出最内层的元素。 对于每层&…

CockroachDB集群部署

CockroachDB集群部署 1、CockroachDB简介 CockroachDB(有时简称为CRDB)是一个免费的、开源的分布式 SQL 数据库&#xff0c;它建立在一个事务性和强一致性的键 值存储之上。它由 PebbleDB(一个受 RocksDB/leveldb 启发的 K/B 存储库)支持&#xff0c;并使用 Raft 分布式共识…

JS进阶-函数剩余参数

函数参数的使用细节&#xff0c;能够提升函数应用的灵活度。 动态参数 arguments是函数内部内置的伪数组变量&#xff0c;它包含了调用函数时传入的所有实参&#xff0c;只存在于函数里 function getSum() {let sum 0for (let i 0; i < arguments.length; i) {sum arg…

性能测试之使用Jemeter对HTTP接口压测

我们不应该仅仅局限于某一种工具&#xff0c;性能测试能使用的工具非常多&#xff0c;选择适合的就是最好的。笔者已经使用Loadrunner进行多年的项目性能测试实战经验&#xff0c;也算略有小成&#xff0c;任何性能测试&#xff08;如压力测试、负载测试、疲劳强度测试等&#…

9.19数电——触发器状态机第四周作业题解计数器(部分)

触发器 RS 1.输出置0 2.置1 3.输出保持不变 S&#xff1a;是置位信号&#xff0c;为1时说要置为1&#xff1b;为0时要置为0&#xff1b; R&#xff1a;是复位信号&#xff0c;为1时就要无条件置为0&#xff0c;为0时保持寄存器原状态 如果要置为0&#xff0c;必要条件…

uniapp——实现base64格式二维码图片生成+保存二维码图片——基础积累

最近在做二维码推广功能&#xff0c;自从2020年下半年到今天&#xff0c;大概有三年没有用过uniapp了&#xff0c;而且我之前用uniapp开发的程序还比较少&#xff0c;因此很多功能都浪费了很多时间去查资料&#xff0c;现在把功能记录一下。 这里写目录标题 效果图1.base64生成…

卤制品配送经营商城小程序的用处是什么

卤制品也是食品领域重要的分支&#xff0c;尤其对年轻人来说&#xff0c;只要干净卫生好吃价格合理&#xff0c;那复购率宣传性自是不用说&#xff0c;而随着互联网发展&#xff0c;传统线下门店也须要通过线上破解难题或进一步扩大生意。 而商城小程序无疑是商家通过线上私域…

2023-9-26 JZ 复杂链表的复制

题目链接&#xff1a;复杂链表的复制 import java.util.*; /* public class RandomListNode {int label;RandomListNode next null;RandomListNode random null;RandomListNode(int label) {this.label label;} } */ public class Solution {public RandomListNode Clone(Ra…

Docker 容器编排

是什么 Docker-Compose是 Docker 官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。 Compose 是 Docker 公司推出的一个工具软件&#xff0c;可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml&#xff0c;写好多个…

【Java 基础篇】Java JUnit 使用详解

JUnit是一个用于编写和运行单元测试的Java框架。它是开发高质量、可维护和可扩展的Java应用程序的关键工具之一。本文将详细介绍JUnit的使用&#xff0c;包括JUnit的安装、基本用法、常见注解、测试套件、参数化测试等内容。 什么是单元测试&#xff1f; 在深入JUnit之前&…

【深度学习实验】卷积神经网络(二):自定义简单的二维卷积神经网络

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 二维互相关运算&#xff08;corr2d&#xff09; 2. 二维卷积层类&#xff08;Conv2D&#xff09; a. __init__&#xff08;初始化&#xff09; b. forward(前向传…

web浏览器公网远程访问jupyter notebook【内网穿透】

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

【数据结构-树】哈夫曼树

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

【算法思想-排序】根据另一个数组次序排序 - 力扣 1122 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

超越代写!5步教你轻松利用ChatGPT创作文本

任何尝试用 ChatGPT 写过“写一篇关于【主题】的文章”的人都知道一个真相&#xff1a; ChatGPT 根本写不好&#xff0c;这不是秘密。如果你怀疑我&#xff0c;试试用它或者任何 AI 写作工具去写一篇博客文章&#xff0c;结果它都会写出非常糟糕的、没人会想看的内容。 但是我…

springboot基于SpringBoot的冬奥会科普平台springboot21

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

基于微信小程序的动漫论坛平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

RocketMQ生产环境常见问题分析与总结

关于零拷贝与顺序写 一、RocketMQ如何保证消息不丢失 1、哪些环节会有丢消息的可能&#xff1f; 我们考虑一个通用的MQ场景&#xff1a; 其中&#xff0c;1&#xff0c;2&#xff0c;4三个场景都是跨网络的&#xff0c;而跨网络就肯定会有丢消息的可能。 然后关于3这个环节…