面试准备
1、mysql面试题,基本知识准备
①连接查询
②limit用法
③存储过程
④mysql查询执行路径
⑤索引
⑥mysql优化
2、接口自动化框架:testng、mybatis、reportNg、maven、git
一、注解
1、执行顺序:@BeforeSuite > @BeforeTest > @BeforeMethod > @Test > @AfterMethod > @AfterTest > @AfterSuite
2、tesgng.xml文件:
<suite name = "TestNG Suite"> //自定义的测试集合名称
<test name = "test1"> //自定义的测试名称
<classes> //定义被运行的测试类
<class name = "cn.gloryroad.FirstTestNGDemo" /> //测试类的路径
<class name = "cn.gloryroad.NewTest" />
</classes>
</test>
</suite>
3、分组:Test(groups={"car","suv"}),在testng.xml中增加配置<groups><run><include><include name = "car" />
执行cn.gloryroad.Grouping测试类中定义的含有分组为“动物”的分组
<suite name = "TestNG Suite">
<test name = "Grouping">
<groups>
<run>
<include name = "动物" />
</run>
</groups>
<classes>
<class name = "cn.gloryroad.Grouping"/>
</classes>
</test>
</suite>
需要执行多个分组时1:
<suite name = "TestNG Suite">
<test name = "Grouping">
<groups>
<run>
<include name = "动物" /> //name分组名称
<include name = "人" />
</run>
</groups>
<classes>
<class name = "cn.gloryroad.Grouping"/>
</classes>
</test>
</suite>
执行多个分组2
<suite name = "TestNG Suite">
<test name = "Grouping">
<groups>
<define name = "All">
<include name = "动物" />
<include name = "人" />
</define>
<define name = "peaple">
<include name = "人" />
</define>
<run>
<include name = "All" />(选择要执行的define的name属性)
</run>
</groups>
<classes>
<class name = "cn.gloryroad.Grouping"/>
</classes>
</test>
</suite>
4、alwaysRun属性,配合分组,alwaysRun=true,属性配置在BeforeClass和AfterClass,可以保证执行分组时需要执行的测试前置是生效的
@Test(alwaysRun=true)
5、方法的依赖测试
@Test(dependsOnMethod = {"方法名称"})
被依赖的方法优先于此方法执行,被依赖的方法执行失败,则依赖方法跳过执行。如果需要不论被依赖方法是否执行成功,依赖方法都执行,
可配合alwaysRun属性=true。
6、不执行配置:、
@Test(enabled=false)添加此注解的方法不执行,默认为true,执行
7、超时时间:
@Test(timeOut=100)
运行此方法的时间超过100毫秒则失败
8、维持测试用例的执行顺序:
《suite》
<test name= "test1" preserve-order="true"(配置改属性,则不按下面的classes顺序执行。
9、《test name="test" enable="true"》//enable=“false”,则该test不执行。
10、Parameters注解参数化
一、配置testng.xml:的parameter标签,key、value,注意value需要为字符串类型,如果需要特殊处理需要在测试方法中java处理
<?xml version=
"1.0"
encoding=
"UTF-8"
?><!DOCTYPE suite SYSTEM
"http://testng.org/testng-1.0.dtd"
>
<suite name=
"Suite1"
>
<test name=
"test1"
>
<parameter name=
"myName"
value=
"manisha"
/>
<classes>
<
class
name=
"ParameterizedTest1"
/>
</classes>
</test>
</suite>
public
class
ParameterizedTest1 {
@Test
@Parameters
(
"myName"
)
public
void
parameterTest(String myName) {
System.out.println(
"Parameterized value is : "
+ myName);
}
}
public boolean validate(final Integer prineNumber){
for (int i = 2; i < (prineNumber / 2); i++) {
if (prineNumber % i ==0){
return false;
}
}
return true;
}
}
测试类:
public class ParamTestWithDataProvider { private PrimeNumberChecker primeNumberChecker; @BeforeMethod public void initialize(){ primeNumberChecker = new PrimeNumberChecker(); } @DataProvider(name = "test1") public static Object[][] primeNumbers(){ return new Object[][]{{2,true},{6,false},{19,true}}; } @Test(dataProvider = "test1",dataProviderClass =ParamTestWithDataProvider.class)
public void testPrimeNumberChecker(Integer inputNumber,boolean expectedResult){
System.out.println(inputNumber+" "+expectedResult);
Assert.assertEquals(expectedResult,primeNumberChecker.validate(inputNumber));
}
}
13、ITestResult接口:测试方法是否执行成功,方再AfterMethod,成功或失败后执行对应方法
public class TestNG_ITestResultDemo { @Test public void testMethod1(){ System.out.println("Running--> testMethod1"); Assert.assertTrue(false); } @Test public void testMethd2(){ System.out.println("Running--> testMethod2"); Assert.assertTrue(true); } @AfterMethod public void afterMethod(ITestResult testResult){ if (testResult.getStatus()==ITestResult.FAILURE) { //监听执行测试方法,如果失败,打印失败的方法名 System.out.println("Failed:"+testResult.getMethod().getMethodName()); }else if (testResult.getStatus()==ITestResult.SUCCESS){ //如果成功,打印成功的方法名 System.out.println("Successful:"+testResult.getName()); } } }
14、监听器
①IInokedMethodListener监听
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//被监听class @Listeners(CustomListener1.class) public class TestNG_ListenersTest1 { @BeforeClass public void setUp(){ System.out.println("Code in before class"); } @AfterClass public void cleanUp(){ System.out.println("Code in after class"); } @Test public void testMethod1(){ System.out.println("TestNG_ListenersTest1:Code in testMethod1"); Assert.assertTrue(true); } @Test public void testMethod2(){ System.out.println("TestNG_ListenersTest1:Code in testMethod2"); Assert.assertTrue(false); } } //监听Class public class CustomListener1 implements IInvokedMethodListener{ @Override public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { //在测试类里的每一个方法运行前跑,注意是每个方法,不止test,还包括Before和after //ITestResult获取监听执行的类名,IInvokedMethod监听方法 System.out.println("BeforeInvocation"+iTestResult.getTestClass().getName()+"-->"+ iInvokedMethod.getTestMethod().getMethodName()); } @Override public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { //在测试类里的每一个方法运行后跑 System.out.println("AfterInvocation"+iTestResult.getTestClass().getName()+"-->"+ iInvokedMethod.getTestMethod().getMethodName()); } } //testng.xml文件 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Listeners TestSuite"> <listeners> <listener class-name="listenerspackage.CustomListener1"></listener> </listeners> <test name="Application Test1"> <classes> <class name="test.TestNG_ListenersTest1"></class> </classes> </test> </suite>
②ITestListener监听
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//监听Class public class CustomListener2 implements ITestListener{ @Override public void onTestStart(ITestResult iTestResult) { //测试方法(带test注解的方法)开始时执行此方法 System.out.println("onTestStart--> test name:"+iTestResult.getName()); //返回测试方法的方法名 } @Override public void onTestSuccess(ITestResult iTestResult) { //测试方法(带test注解的方法)开如果测试方法执行成功,再执行此方法 System.out.println("onTestSuccess--> test name:"+iTestResult.getName()); } @Override public void onTestFailure(ITestResult iTestResult) { //测试方法(带test注解的方法)开如果测试方法执行失败,再执行此方法 System.out.println("onTestFailure--> test name:"+iTestResult.getName()); } @Override public void onTestSkipped(ITestResult iTestResult) { //跳过执行时执行此方法代码 } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) { //定义测试用例失败中有6个断言,5个成功,1个失败,可以定位为成功 } @Override public void onStart(ITestContext iTestContext) { //在tesgng.xml的test标签执行前执行 System.out.println("onStart--> test tag name;"+iTestContext.getName()); //获取标签的名字 //test标签中所有类中的测试方法,返回数组 ITestNGMethod methods[] = iTestContext.getAllTestMethods(); System.out.println("Test标签里面要执行的测试方法"); for (ITestNGMethod method:methods) { System.out.println(method.getMethodName()); } } @Override public void onFinish(ITestContext iTestContext) { //在testng.xml的test标签执行结束后执行 System.out.println("onFinish--> test tag name:"+iTestContext.getName()); } } //被测试Class @Listeners(CustomListener2.class) public class TestNG_ListenersTest2 { @BeforeClass public void setUp(){ System.out.println("Code in before class"); } @AfterClass public void cleanUp(){ System.out.println("Code in after class"); } @Test public void testMethod1(){ System.out.println("TestNG_ListenersTest1:Code in testMethod1"); Assert.assertTrue(true); } @Test public void testMethod2(){ System.out.println("TestNG_ListenersTest1:Code in testMethod2"); Assert.assertTrue(false); } } //testng.xml <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Listeners TestSuite"> <listeners> <listener class-name="listenerspackage.CustomListener2"></listener> </listeners> <test name="Application Test1"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> <test name="Application Test2"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> </suite>
③ISuiteListener监听
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//监听Class public class CustomListener3 implements ISuiteListener{ @Override public void onStart(ISuite iSuite) { //当suite标签开始执行时 System.out.println("onStart:suite开始执行之前"); } @Override public void onFinish(ISuite iSuite) { //当suite标签执行完后执行该方法中代码 System.out.println("OnFinish:suite执行完成后执行"); } } //testng.xml <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Listeners TestSuite"> <!--加上listeners标签后,被测试方法中不用加listener注解--> <listeners> <listener class-name="listenerspackage.CustomListener2"></listener> </listeners> <test name="Application Test1"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> <test name="Application Test2"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> </suite>
④实际使用时将所有监听器放在一个Class中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//监听Class public class CustomListener implements IInvokedMethodListener,ITestListener,ISuiteListener{ //IInvokedMethodListener @Override public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { //在测试类里的每一个方法运行前跑,注意是每个方法,不止test,还包括Before和after //ITestResult获取监听执行的类名,IInvokedMethod监听方法 System.out.println("BeforeInvocation"+iTestResult.getTestClass().getName()+"-->"+ iInvokedMethod.getTestMethod().getMethodName()); } @Override public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { //在测试类里的每一个方法运行后跑 System.out.println("AfterInvocation"+iTestResult.getTestClass().getName()+"-->"+ iInvokedMethod.getTestMethod().getMethodName()); } //ITestListener @Override public void onTestStart(ITestResult iTestResult) { //测试方法(带test注解的方法)开始时执行此方法 System.out.println("onTestStart--> test name:"+iTestResult.getName()); //返回测试方法的方法名 } @Override public void onTestSuccess(ITestResult iTestResult) { //测试方法(带test注解的方法)开如果测试方法执行成功,再执行此方法 System.out.println("onTestSuccess--> test name:"+iTestResult.getName()); } @Override public void onTestFailure(ITestResult iTestResult) { //测试方法(带test注解的方法)开如果测试方法执行失败,再执行此方法 System.out.println("onTestFailure--> test name:"+iTestResult.getName()); } @Override public void onTestSkipped(ITestResult iTestResult) { //跳过执行时执行此方法代码 } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) { //定义测试用例失败中有6个断言,5个成功,1个失败,可以定位为成功 } @Override public void onStart(ITestContext iTestContext) { //在tesgng.xml的test标签执行前执行 System.out.println("onStart--> test tag name;"+iTestContext.getName()); //获取标签的名字 //test标签中所有类中的测试方法,返回数组 ITestNGMethod methods[] = iTestContext.getAllTestMethods(); System.out.println("Test标签里面要执行的测试方法"); for (ITestNGMethod method:methods) { System.out.println(method.getMethodName()); } } @Override public void onFinish(ITestContext iTestContext) { //在testng.xml的test标签执行结束后执行 System.out.println("onFinish--> test tag name:"+iTestContext.getName()); } //ISiteListener @Override public void onStart(ISuite iSuite) { //当suite标签开始执行时 System.out.println("onStart:suite开始执行之前"); } @Override public void onFinish(ISuite iSuite) { //当suite标签执行完后执行该方法中代码 System.out.println("OnFinish:suite执行完成后执行"); } } //testng.xml <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Listeners TestSuite"> <!--加上listeners标签后,被测试方法中不用加listener注解--> <listeners> <listener class-name="listenerspackage.CustomListener"></listener> </listeners> <test name="Application Test1"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> <test name="Application Test2"> <classes> <class name="test.TestNG_ListenersTest2"></class> </classes> </test> </suite>
15、Reporter:打印tesgng报告
Reporter.log("TestNG_ReportsAmdLogs--> testMethod1",true);//同时在控制台打印,第一个参数字符串,第二个参数是否在控制台打印
解决问题:idea执行testng.xml后,没有输出testtest-output报告
idea--》run--》Edit Configuratinos--》Listeners-->勾选Use default reporters
3、Jenkins自动化部署,构建、CI执行、ReportNg测试报告()
①ReportNG测试报告:
pom依赖:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!--reportng--> <dependency> <groupId>org.uncommons</groupId> <artifactId>reportng</artifactId> <version>1.1.4</version> </dependency> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>3.0</version>
testng.xml增加监听:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > <suite name="test" parallel="false"> <test name ="test" preserve-order="false"> <classes> <class name="test.ReporterNGTest"></class> </classes> </test> <listeners> <listener class-name="org.uncommons.reportng.HTMLReporter"></listener> </listeners> </suite>
查看报告:test-output目录下的html目录查看index.html。
②、reportng配合maven,通过mvn命令执行,此方式通常和CI结合使用(Jenkins结合参考:https://www.cnblogs.com/byron0918/p/5400836.html,待实践)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng-reportng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<properties>
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
<property>
<name>listener</name>
<value>org.uncommons.reportng.HTMLReporter</value>
</property>
</properties>
<workingDirectory>target/</workingDirectory>
</configuration>
</plugin>
③Jenkins
④extent Report 测试报告,更美观:
https://www.cnblogs.com/wangkc/p/report.html
4、TDD,测试驱动开发框架
5、性能测试,基本监控命令、测试流程、有缓存等问题的仿真系统、全流程性能测试。
6、java、python基本面试题
7、根据具体需求给出必要的接口设计
①红包系统为例,接口功能如下:
1、获取活动列表
2、查询活动详情
3、获取红包种类/模板
4、查询红包详情
5、领取红包(待领取/已领取/已兑现/已提现)
6、获取用户红包列表
7、查看用户是否领取某个活动下的红包(模板)
8、获取用户全部红包列表
9、兑现红包
10、红包可提现余额
考虑思路:
8、七层协议和四层协议
9、mock框架:
10、内存数据库
11、web自动化应用:
public class testng_selenium{
WebDriver driver;
String baseURL;
@BeforeClass
@Paramters({"browser"})
public void setUp(String browser){
baseURL = "https://www.baidu.com";
if(browser.equalsIgnoreCase("IE")){
System.setProperty("webdriver.ie.driver","D:\\works\ieDriver.exe");
driver = new InternetExplorerDriver();
}else if(browser.equalsIgnoreCase("chorme")){
System.setProperty("webdriver.chrome.driver","D:\\works\chromeDriver.exe");
driver = new ChromeDriver();
}
driver.manage().window().maximize();
driver.get(baseURL);
}
@Test
public void tetLogic(){
WebElement loginLink = driver.findElement(By.id("js-signin-btn"));
loginLink.click();
WebElement userNameField = driver.findElemnet(By.xpath("");
userNameField.sendKeys("13444444444");
WebElement loginButton = driver.findElement(By.xpath("//input[@value='登录']"));
loginButton.click();
}
}
12、web自动化之PageObjectModel模型:把页面封装成单独的页面类,在页面类中把页面中的元素都封装到静态方法中,返回WebElement类型的元素,这样可以用类名调用方法来使用该元素,可以创建更多的测试类对该元素进行操作。测试代码只需要调用和传值,方便阅读和维护。
①创建页面类用于存放页面元素及对元素的执行动作:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package pageclasses; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; public class HomePage1 { public static WebElement element = null; /** * 返回登录按钮元素 */ public static WebElement loginIn(WebDriver driver){ element = driver.findElement(By.xpath("")); return element; } /** * 对查找的元素进行操作 */ public static void clickLoginIn(WebDriver driver){ element = loginIn(driver); element.click(); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package pageclasses; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; //先定位页面元素,然后对页面元素初始化操作,下面是对页面元素的执行动作 public class FreeCoursePageFactory1 { WebDriver driver; //定位页面元素 @FindBy(xpath = "") WebElement freeCourseLink; @FindBy(id = "") WebElement maintainanceAndTestLink; @FindBy(name = "") WebElement testLink; public FreeCoursePageFactory1(WebDriver driver){ this.driver=driver; //初始化上面找到的所有元素, PageFactory.initElements(driver,this); } //元素初始化后,对页面元素的操作 public void clickFreeCourseLink(){ freeCourseLink.click(); } public void clickMaintainanceAndTestLink(){ maintainanceAndTestLink.click(); } public void clickTestLink(){ testLink.sendKeys(""); } }
②执行class直接用封装对象的类名.方法名调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package pomtestcase; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import pageclasses.FreeCoursePageFactory1; import pageclasses.HomePage1; import java.util.concurrent.TimeUnit; public class PageObjectModel1 { private WebDriver driver; private String baseUrl; FreeCoursePageFactory1 freeCoursePageFactory1; @BeforeClass public void setUp() throws Exception{ driver = new ChromeDriver(); baseUrl = "http://www.baidu.com"; freeCoursePageFactory1 = new FreeCoursePageFactory1(driver); //窗口最大化 driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void test(){ //元素初始化后,直接调用对象的方法即可 freeCoursePageFactory1.clickFreeCourseLink(); freeCoursePageFactory1.clickMaintainanceAndTestLink(); freeCoursePageFactory1.clickTestLink(); } @AfterClass public void tearDown(){ } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package pomtestcase; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import pageclasses.HomePage1; import java.util.concurrent.TimeUnit; public class PageObjectModel { private WebDriver driver; private String baseUrl; @BeforeClass public void setUp() throws Exception{ driver = new ChromeDriver(); baseUrl = "http://www.baidu.com"; //窗口最大化 driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void test(){ driver.get(baseUrl); //类名直接调用pageClasses中封装的页面元素可执行方法: HomePage1.clickLoginIn(driver); } @AfterClass public void tearDown(){ } }