Junit4教程

合集下载

Junit4单元测试框架的常用方法介绍

Junit4单元测试框架的常用方法介绍

Junit4单元测试框架的常⽤⽅法介绍Junit 介绍:Junit是⼀套框架(⽤于JAVA语⾔),由 Erich Gamma 和 Kent Beck 编写的⼀个回归测试框架(regression testing framework),即⽤于⽩盒测试。

本⽂介绍的内容:1 Junit Myeclipse测试类的⽣成2 JUnit 4 常⽤的⼏个annotation 介绍与使⽤ (@Before @After @Test @Ignore @BeforeClass @AfterClass)3 常⽤的断⾔介绍4 特殊的处理(限时测试,异常测试)5 参数化配置(@Parameters)准备测试代码测试的⽅法(正确、错误⽅法、死循环、抛异常)LogicServicepackage com.logic;public class LogicService {public int add(int x ,int y){ //加法return x+y;}public int sub(int x ,int y){ //减法return x-y;}public int div(int x ,int y){ //除法return x/y;}public int div2(int x ,int y){ //除法做了异常判断try {int z = x/y;} catch (Exception e) {e.printStackTrace();}return x/y;}public void loop(int x ,int y){ //死循环for(;;)x=y;}public void unCompleted(int x ,int y){ //未完成的模块//还在开发中}}⼀ Myeclipse测试类的⽣成1 对需要测试的类点右键 NEW ⼀个Junit Test Case2 点击NEXT注意 1 选择NEW Junit 4 test2 source folder 是默认会填写上之前右键NEW的那个类,如果不是的话,请⾃⾏进⾏修改3 package 默认会填写当前的包名个⼈建议重新开个测试包-即在包后⾯加上.test 表⽰是单元测试⽤例专⽤包与源代码分离4 name 默认会在之前右键NEW的那个类的基础的后⾯加上Test 如果不是的话,建议⾃⾏进⾏修改,便于标⽰5 初始化的⽅法,我⼀般会勾上个setUp,这个请随意。

Robotium自动化测试框架实用教程(图)

Robotium自动化测试框架实用教程(图)

Robotium⾃动化测试框架实⽤教程(图)⼀、简介Robotium是⼀款国外的Android⾃动化测试框架,主要针对Android平台的应⽤进⾏⿊盒⾃动化测试,它提供了模拟各种⼿势操作(点击、长按、滑动等)、查找和断⾔机制的API,能够对各种控件进⾏操作。

Robotium结合Android官⽅提供的测试框架达到对应⽤程序进⾏⾃动化的测试。

另外,Robotium 4.0版本已经⽀持对WebView的操作。

Robotium 对Activity,Dialog,Toast,Menu 都是⽀持的。

⼆、相关下载源码获取:/p/robotium/源API⽂档:/svn/doc/index.htmlrobotium5.1下载和最新API⽂档:/s/1bnlO8MF官⽅例⼦记事本:/s/1qWLVL72重签名⼯具:/s/1i3H0tKD三、常⽤语法1.等待timeout毫秒⼀个名字为name的Activity启动: waitForActivity(String name, int timeout)实例:assertTrue("⽆法启动启动类", solo.waitForActivity ("MainActivity", 30000));2.Robotium将睡眠设置的毫秒数:sleep(int time)实例:solo.sleep(5000)3.清空EditText的内容:clearEditText(android.widget.EditText editText)实例:solo.clearEditText((EditText)solo.getView ("edtInsertName"))4.根据按钮上的⽂字点击按钮:clickOnButton(String text)实例:solo.clickOnButton("^绿⾊$");5.根据⽂字点击控件:clickOnText(String text)实例:solo.clickOnText("控件上显⽰⽂字");6.输⼊内容:enterText(android.widget.EditText editText, String text)solo.enterText((EditText)solo.getView("edtInsertName"), "说些什么好呢?");7.返回:goBack()8.截屏并保存为设置的名字:takeScreenshot(String name)默认保存在: /sdcard/Robotium-Screenshots/9.解锁屏幕:unlockScreen()四、实战-针对APK进⾏的测试被测试项⽬为,下⾯是实战的具体步骤1. 配置ANDROID_HOM E为android sdk的安卓⽬录,例如:D:\android-sdk2. 在path下添加这两个:%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;3. 需要把APK重新签名,因为robotium要求被测应⽤和测试代码要有⼀致的签名, 所以我们需要把下载到的apk,通过re-sign.jar来产⽣debug key的apk,这个重新⽣成的apk就会跟测试项⽬签名⼀致了4. 下载完后,需要配置ANDROID_HOME,就是安卓SDK的位置,然后把APK拉到图标上,就会⾃动⽣成⼀个debug key的apk,如果⽆法直接单击re-sign.jar运⾏,需要切换到放置该jar⽂件的⽬录,cmd执⾏java -jar re-sign.jar产⽣新apk的过程中会弹出⼀个信息框,记得截下图,因为⾥⾯有两个信息我们等会的代码中需要⽤到5. 安装产⽣的apk。

JUnit4中@Before、@After、@Test等注解的作用

JUnit4中@Before、@After、@Test等注解的作用

JUnit4中@Before、@After、@Test等注解的作⽤JUnit4使⽤Java5中的注解(annotation),以下是JUnit4常⽤的⼏个annotation:@Before:初始化⽅法对于每⼀个测试⽅法都要执⾏⼀次(注意与BeforeClass区别,后者是对于所有⽅法执⾏⼀次)@After:释放资源对于每⼀个测试⽅法都要执⾏⼀次(注意与AfterClass区别,后者是对于所有⽅法执⾏⼀次)@Test:测试⽅法,在这⾥可以测试期望异常和超时时间@Test(expected=ArithmeticException.class)检查被测⽅法是否抛出ArithmeticException异常@Ignore:忽略的测试⽅法@BeforeClass:针对所有测试,只执⾏⼀次,且必须为static void@AfterClass:针对所有测试,只执⾏⼀次,且必须为static void⼀个JUnit4的单元测试⽤例执⾏顺序为:@BeforeClass -> @Before -> @Test -> @After -> @AfterClass;每⼀个测试⽅法的调⽤顺序为:@Before -> @Test -> @After;public class JUnit4Test {@Beforepublic void before() {System.out.println("@Before");}@Test/***Mark your test cases with @Test annotations.*You don’t need to prefix your test cases with “test”.*tested class does not need to extend from “TestCase” class.*/public void test() {System.out.println("@Test");assertEquals(5 + 5, 10);}@Ignore@Testpublic void testIgnore() {System.out.println("@Ignore");}@Test(timeout = 50)public void testTimeout() {System.out.println("@Test(timeout = 50)");assertEquals(5 + 5, 10);}@Test(expected = ArithmeticException.class)public void testExpected() {System.out.println("@Test(expected = Exception.class)");throw new ArithmeticException();}@Afterpublic void after() {System.out.println("@After");}@BeforeClasspublic static void beforeClass() {System.out.println("@BeforeClass");};@AfterClasspublic static void afterClass() {System.out.println("@AfterClass");};};输出结果:@BeforeClass@Before@Test(timeout = 50)@After@Before@Test(expected = Exception.class)@After@Before@Test@After@AfterClass@BeforeClass and @AfterClass@Before and @After在⼀个类中只可以出现⼀次在⼀个类中可以出现多次,即可以在多个⽅法的声明前加上这两个Annotaion标签,执⾏顺序不确定⽅法名不做限制⽅法名不做限制在类中只运⾏⼀次在每个测试⽅法之前或者之后都会运⾏⼀次@BeforeClass⽗类中标识了该Annotation的⽅法将会先于当前类中标识了该Annotation的⽅法执⾏。

Junit4单元测试

Junit4单元测试

Junit4单元测试Junit4单元测试第⼀部分⽤法1.1 常见功能典型配置:/*⽤于配置spring Boot中测试的环境*/@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes = MyBlogApplication.class)/* 开启事务,测试完成默认⾃动回滚,不会弄脏数据库 */@Transactionalpublic class WhoHaveWhatTagsMapperTest {@BeforeClasspublic static void beforeClass() {}@Beforepublic void setUp() throws Exception {}@Afterpublic void tearDown() throws Exception {}@Testpublic void insertWhoHaveWhatTags() throws Exception {}@Testpublic void selectBlogByTag() throws Exception {}@Testpublic void deleteWhoHaveWhatTags() throws Exception {}}@Test:把⼀个⽅法标记为测试⽅法两个属性:excepted;表⽰测试在执⾏中期望抛出的异常类型,如果不抛出,反⽽报错。

timeout:超时抛出异常。

单位毫秒@Test(timeout = 2000)@Test(expected = Exception.class)public void testFactorialException() throws Exception {new Math().factorial(-1);fail("factorial参数为负数没有抛出异常");}@Before:每⼀个测试⽅法执⾏前⾃动调⽤⼀次@After:每⼀个测试⽅法执⾏完⾃动调⽤⼀次@BeforeClass:所有测试⽅法执⾏前执⾏⼀次,在测试类还没有实例化就已经被加载,所以⽤static修饰@AfterClass:所有测试⽅法执⾏完执⾏⼀次,在测试类还没有实例化就已经被加载,所以⽤static修饰@Ignore:暂不执⾏该测试⽅法setup⽅法主要实现测试前的初始化⼯作teardown⽅法主要实现测试完成后垃圾回收⼯作!setup⽅法主要实现测试前的初始化⼯作,teardown⽅法主要实现测试完成后垃圾回收⼯作!测试⽅法的声明要求:名字可以随便取,没有任何限制,但是返回值必须为void,⽽且不能有任何参数。

Intellij IDEA14添加Junit测试

Intellij IDEA14添加Junit测试

在Intellij IDEA开发的时候怎么测试一个接口
首先我们肯定是编写好了接口,如下图
从上图中你能看到,一定要把光标放到接口的后面,然后你按快捷键AIT+Enter,你会看到下面的弹窗
敲回车之后你就会打开下面的界面了
Testing Library 选择测试的方式,后面罗列的几种,我一般选择junit4
class name 你测试的接口名称
Super class 测试接口的父接口
Destination package 测试类要保存的包名称
Member 下面是接口的方法,你勾选需要测试的方法
下面选择需要测试的方法;
当然,下面就是IDEA自动生成的测试类,当这个测试类提示没有相应的类的时候,就表示你没有添加对应的Junit的包,同样AIT +Enter快捷键,打开添加包的窗口,IDEA会自动从官网检查出相关包,你把你需要的那个下载下来就OK了;
看到上图的显示了吗,选择Find JAR on web 回车之后你就会看到如下界面
选择之后会让你选择此包保存在那里,随便选择个位置就行,默认也可以的;
保存好就OK了,你的项目中也添加好了;。

在Eclipse中使用JUnit4进行单元测试

在Eclipse中使用JUnit4进行单元测试

我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的。

但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个函数的其他功能,而这个功能有bug的话,那绝对是一件非常郁闷的事情。

所以说,每编写完一个函数之后,都应该对这个函数的方方面面进行测试,这样的测试我们称之为单元测试。

传统的编程方式,进行单元测试是一件很麻烦的事情,你要重新写另外一个程序,在该程序中调用你需要测试的方法,并且仔细观察运行结果,看看是否有错。

正因为如此麻烦,所以程序员们编写单元测试的热情不是很高。

于是有一个牛人推出了单元测试包,大大简化了进行单元测试所要做的工作,这就是JUnit4。

本文简要介绍一下在Eclipse3.2中使用JUnit4进行单元测试的方法。

首先,我们来一个傻瓜式速成教程,不要问为什么,Follow Me,先来体验一下单元测试的快感!首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。

这个类并不是很完美,我们故意保留了一些Bug用于演示,这些Bug在注释中都有说明。

该类代码如下:package andycpp;public class Calculator ...{private static int result; // 静态变量,用于存储运行结果public void add(int n) ...{result = result + n;}public void substract(int n) ...{result = result - 1; //Bug: 正确的应该是 result =result-n}public void multiply(int n) ...{} // 此方法尚未写好public void divide(int n) ...{result = result / n;}public void square(int n) ...{result = n * n;}public void squareRoot(int n) ...{for (; ;) ; //Bug : 死循环}public void clear() ...{ // 将结果清零result = 0;}public int getResult() ...{return result;}}第二步,将JUnit4单元测试包引入这个项目:在该项目上点右键,点“属性”,如图:在弹出的属性窗口中,首先在左边选择“Java Build Path”,然后到右上选择“Libraries”标签,之后在最右边点击“Add Library…”按钮,如下图所示:然后在新弹出的对话框中选择JUnit4并点击确定,如上图所示,JUnit4软件包就被包含进我们这个项目了。

《Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)》_课后习题

《Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)》_课后习题

第一章【思考题】1、请简述Spring框架的优点。

2、请简述什么是Spring的IoC和DI。

【答案】1、Spring框架的优点如下:(1)非侵入式设计:Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。

(2)方便解耦、简化开发:Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器管理,大大的降低了组件之间的耦合性。

(3)支持AOP:Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,从而提高了程序的复用性。

(4)支持声明式事务处理:只需要通过配置就可以完成对事务的管理,而无需手动编程。

(5)方便程序的测试:Spring提供了对Junit4的支持,可以通过注解方便的测试Spring 程序。

(6)方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。

(7)降低了Java EE API的使用难度:Spring对Java EE开发中非常难用的一些API (如:JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。

2、IoC的全称是Inversion of Control,中文名称为控制反转。

控制反转就是指在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring 容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。

这样,控制权由应用代码转移到了Spring容器,控制权发生了反转。

DI的全称是Dependency Injection,中文称之为依赖注入。

它与控制反转(IoC)的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。

从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。

junit4中Assert断言的使用以及Mockito框架mock模拟对象的简单使用

junit4中Assert断言的使用以及Mockito框架mock模拟对象的简单使用

junit4中Assert断⾔的使⽤以及Mockito框架mock模拟对象的简单使⽤ 编写测试代码时,我们总会有我们对被测⽅法⾃⼰预期的值,以及调⽤被测⽅法后返回的真实执⾏后的值。

需要断⾔这两个值是否相等、抛出异常、hash码等等情况。

这⾥博主主要介绍⼀下简单的断⾔和mock。

如果已经对junit测试有过相对了解的,请略过这篇⽂章。

下⾯是我准备的节点类:1package demo;23/**4 * @author Lcc5 *6*/7public class Node {8private int value;910public Node(int value) {11this.value = value;12 }1314public String toString() {15return "它本来的值是:" + value;16 }1718public int getValue() {19return value;20 }2122public void setValue(int value) {23this.value = value;24 }2526 }以及节点类的冒泡排序算法:1package demo;23/**4 * @author Lcc5 *6*/7public class BubbleSort {89public Node[] bubbleSort(Node[] a) {1011for (int i = 0; i < a.length; i++) {12for (int j = 0; j < a.length; j++) {13if (a[i].getValue() > a[j].getValue()) {14 Node temp = a[i];15 a[i] = a[j];16 a[j] = temp;17 }18 }19 }20 System.out.println(a[1].toString());// 没有使⽤mock时输出:"它本来的值是:221return a;22 }2324 }现在我们需要测试冒泡排序⽅法,当然由于这个⽅法⽐较简单其实不⽤mock也可以,但是博主⼀时间也想不出来有什么好的例⼦。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JUnit4概述JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。

先简单解释一下什么是Annotation,这个单词一般是翻译成元数据。

元数据是什么?元数据就是描述数据的数据。

也就是说,这个东西在Java里面可以用来和public、static等关键字一样来修饰类名、方法名、变量名。

修饰的作用描述这个数据是做什么用的,差不多和public 描述这个数据是公有的一样。

想具体了解可以看Core Java2。

废话不多说了,直接进入正题。

我们先看一下在JUnit 3中我们是怎样写一个单元测试的。

比如下面一个类:public class AddOperation {public int add(int x,int y){return x+y;}}我们要测试add这个方法,我们写单元测试得这么写:import junit.framework.TestCase;import static org.junit.Assert.*;public class AddOperationTest extends TestCase{public void setUp() throws Exception {}public void tearDown() throws Exception {}public void testAdd() {System.out.println(\"add\");int x = 0;int y = 0;AddOperation instance = new AddOperation();int expResult = 0;int result = instance.add(x, y);assertEquals(expResult, result);}}可以看到上面的类使用了JDK5中的静态导入,这个相对来说就很简单,只要在import关键字后面加上static关键字,就可以把后面的类的static的变量和方法导入到这个类中,调用的时候和调用自己的方法没有任何区别。

我们可以看到上面那个单元测试有一些比较霸道的地方,表现在:1.单元测试类必须继承自TestCase。

2.要测试的方法必须以test开头。

如果上面那个单元测试在JUnit 4中写就不会这么复杂。

代码如下:import junit.framework.TestCase;import org.junit.After;import org.junit.Before;import org.junit.Test;import static org.junit.Assert.*;/**** @author bean*/public class AddOperationTest extends TestCase{public AddOperationTest() {}@Beforepublic void setUp() throws Exception {}@Afterpublic void tearDown() throws Exception {}@Testpublic void add() {System.out.println(\"add\");int x = 0;int y = 0;AddOperation instance = new AddOperation();int expResult = 0;int result = instance.add(x, y);assertEquals(expResult, result);}}我们可以看到,采用Annotation的JUnit已经不会霸道的要求你必须继承自TestCase了,而且测试方法也不必以test开头了,只要以@Test元数据来描述即可。

从上面的例子可以看到在JUnit 4中还引入了一些其他的元数据,下面一一介绍:@Before:使用了该元数据的方法在每个测试方法执行之前都要执行一次。

@After:使用了该元数据的方法在每个测试方法执行之后要执行一次。

注意:@Before和@After标示的方法只能各有一个。

这个相当于取代了JUnit以前版本中的setUp和tearDown方法,当然你还可以继续叫这个名字,不过JUnit不会霸道的要求你这么做了。

@Test(expected=*.class)在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue (true)来测试。

现在,通过@Test元数据中的expected属性。

expected属性的值是一个异常的类型@Test(timeout=xxx):该元数据传入了一个时间(毫秒)给测试方法,如果测试方法在制定的时间之内没有运行完,则测试也失败。

@ignore:该元数据标记的测试方法在测试中会被忽略。

当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。

同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。

比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

在Eclipse中使用JUnit4进行单元测试(初级篇)我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的。

但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个函数的其他功能,而这个功能有bug的话,那绝对是一件非常郁闷的事情。

所以说,每编写完一个函数之后,都应该对这个函数的方方面面进行测试,这样的测试我们称之为单元测试。

传统的编程方式,进行单元测试是一件很麻烦的事情,你要重新写另外一个程序,在该程序中调用你需要测试的方法,并且仔细观察运行结果,看看是否有错。

正因为如此麻烦,所以程序员们编写单元测试的热情不是很高。

于是有一个牛人推出了单元测试包,大大简化了进行单元测试所要做的工作,这就是JUnit4。

本文简要介绍一下在Eclipse3.2中使用JUnit4进行单元测试的方法。

首先,我们来一个傻瓜式速成教程,不要问为什么,Follow Me,先来体验一下单元测试的快感!首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。

这个类并不是很完美,我们故意保留了一些Bug用于演示,这些Bug在注释中都有说明。

该类代码如下:package andycpp;public class Calculator ...{private static int result; // 静态变量,用于存储运行结果public void add(int n) ...{result = result + n;}public void substract(int n) ...{result = result - 1; //Bug: 正确的应该是result =result-n}public void multiply(int n) ...{} // 此方法尚未写好public void divide(int n) ...{result = result / n;}public void square(int n) ...{result = n * n;}public void squareRoot(int n) ...{for (; ;) ; //Bug : 死循环}public void clear() ...{ // 将结果清零result = 0;}public int getResult() ...{return result;}}第二步,将JUnit4单元测试包引入这个项目:在该项目上点右键,点“属性”,如图:在弹出的属性窗口中,首先在左边选择“Java Build Path”,然后到右上选择“Libraries”标签,之后在最右边点击“Add Library…”按钮,如下图所示:然后在新弹出的对话框中选择JUnit4并点击确定,如上图所示,JUnit4软件包就被包含进我们这个项目了。

第三步,生成JUnit测试框架:在Eclipse的Package Explorer中用右键点击该类弹出菜单,选择“New à JUnit Test Case”。

如下图所示:在弹出的对话框中,进行相应的选择,如下图所示:点击“下一步”后,系统会自动列出你这个类中包含的方法,选择你要进行测试的方法。

此例中,我们仅对“加、减、乘、除”四个方法进行测试。

如下图所示:之后系统会自动生成一个新类CalculatorTest,里面包含一些空的测试用例。

你只需要将这些测试用例稍作修改即可使用。

完整的CalculatorTest代码如下:package andycpp;import static org.junit.Assert.*;import org.junit.Before;import org.junit.Ignore;import org.junit.Test;public class CalculatorTest ...{private static Calculator calculator = new Calculator();@Beforepublic void setUp() throws Exception ...{calculator.clear();}@Testpublic void testAdd() ...{calculator.add(2);calculator.add(3);assertEquals(5, calculator.getResult());}@Testpublic void testSubstract() ...{calculator.add(10);calculator.substract(2);assertEquals(8, calculator.getResult());}@Ignore("Multiply() Not yet implemented")@Testpublic void testMultiply() ...{}@Testpublic void testDivide() ...{calculator.add(8);calculator.divide(2);assertEquals(4, calculator.getResult());}}第四步,运行测试代码:按照上述代码修改完毕后,我们在CalculatorTest类上点右键,选择“Run As à JUnit Test”来运行我们的测试,如下图所示:运行结果如下:进度条是红颜色表示发现错误,具体的测试结果在进度条上面有表示“共进行了4个测试,其中1个测试被忽略,一个测试失败”至此,我们已经完整体验了在Eclipse中使用JUnit的方法。

相关文档
最新文档