测试开发常问面试题

Postman

Postman实现接口关联

  • 步骤
    • 通过正则表达式或则JSON提取器取值的方式,提取需要的参数。
    • 将参数设置为全局变量或则环境变量。
    • 在之后接口中,通过{{全局变量/环境变量}}代替要替换的参数值。
- JSON提取器方式
var jsonData = JSON.parse(responseBody);
pm.environment.set("token",jsonData.data.accessToken);
- 正则表达式
var jsonData = reponseBody.match(new RegExp('"accessToken":(*.?)'));
pm.globals.set("token",jsonData[1])

Postman实现参数化

  • 内置函数。
    • {{$randomint}}:添加0-1000之间的随机整数。
    • {{$guid}}:添加一个V4风格的GUID
    • {{$timestamp}}: 添加当前的时间戳,精确到秒
    • {{$randomFullName}}:随机全名(名字 姓氏)
    • {{ $randomBoolean}}: 随机布尔值 (true/false)
  • Pre-request-Script页签中使用代码实现
    • 前置脚本设置自定义变量。
  • 全局变量/环境变量/Collection变量
    • 后置脚本设置提取变量。
  • CSV/JSON文件。
    • 关键点1:{{变量名}}:变量名同CSV第一行设置的变量名和JSON文件设置变量名。
    • 关键点2:通过Run Configuration->Data导入文件->设置Iterations。

Jmeter

Jmeter实现接口关联

  • 步骤
    • 在测试计划中添加一个线程组,然后添加取样器。
    • 对线程组右键添加后置处理器→正则表达式提取器/JSON提取器/Xpath提取器。

在这里插入图片描述

  • APPly to:作用范围:
    • Main sample and sub-samples:作用于父节点的取样器及对应子节点的取样器
    • Main sample only:仅作用于父节点的取样器
    • Sub-samples only:仅作用于子节点的取样器
    • JMeter Variable:作用于jmeter变量(输入框内可输入jmeter的变量名称)
  • 要检查的响应字段:
    • Body(unescaped):主体
    • Body as a Document:从不同类型的文件中提取文本
    • Response Headers:响应信息头
    • Request Headers:请求信息头
    • URL:统一资源定位符
  • 模板:
    • $0$代表这一组结果的全部,
    • $1$代表这一组结果的第1个,以此类推;
    • $1$$2$代表该正则表达式一组结果中的第1个和第2个,俩结果挨在一起中间没有间隔;
    • $3$,$4$代表该正则表达式一组结果中的第3个和第4个,俩结果间有一个逗号相连。

在这里插入图片描述

  • Variable names : 名称
  • JSONPath Expression:JSON表达式
  • Match Numbers:匹配哪个,可为空即默认第一个
  • Default Value:未取到值的时候默认值
  - 正则表达式提取器
    -  `<title>百度一下,你就知道</title><title>百度一下,你就知道</title>` -> `<title>(.*?)</title>`
    - `021-1234-1234`->`(.*?)-(.*?)-(.*?)\n`
  - XPath提取器
    - `//a[@id='kw']: 在HTML页面中,找出a标签(有一个属性为id,且id的值为kw)`
    - ` //a : 找出所有的a标签`
  - JSON提取器

Jmeter实现参数化

  • 用户定义的变量:

    • 作用:定义全局变量。
    • 局限性:每次取值(无论是否相同的用户)都是固定值。
  • 用户参数:

    • 作用:保证不同的用户针对同一组参数,可以取到不同的值。
    • 局限性:同一个用户在多次循环时,取到相同的值。
  • csv数据文件设置:

    • 作用:保证不同的用户及同一用户多次循环时,都可以取到不同的值。
    • 局限性:需要手动进行测试数据的设置。
  • 函数:

    • 作用:保证不同的用户及多次循环时,都可以取到不同的值,不需要提前设置
    • 局限性:输入数据有特定的业务要求时无法使用(如:登录时的用户名密码)

Selenium参数化

import json
import time
import unittest
from parameterized import parameterized
from ddt.tpshop import utils
from ddt.tpshop.page.login_page import LoginProxy
from ddt.tpshop.utils import DriverUtil
class TestLogin(unittest.TestCase):
	def build_data(self):
		test_data = []
		with open("../data/testData.json", encoding='UTF-8') as f:
		json_data = json.load(f)
		for login_data in json_data.values():
		test_data.append((login_data.get("username"),
		login_data.get("password"),
		login_data.get("code"),
		login_data.get("is_success"),
		login_data.get("expect")))
		print("test_data=", test_data)
		return test_data
	@classmethod
	def setUpClass(cls):
		cls.driver = DriverUtil.get_driver()
		cls.login_proxy = LoginProxy()
	@classmethod
	def tearDownClass(cls):
		DriverUtil.quit_driver()
	def setUp(self):
		# 进入首页
		self.driver.get("http://localhost")
		# 点击登录链接
		self.driver.find_element_by_link_text("登录").click()
	@parameterized.expand(self.build_data)
	def test_add(self, username, password, code, is_success, expect):
		print('username={} password={} code={} is_success={} expect={}'.
		format(username, password, code, is_success, expect))
		# 登录
		self.login_proxy.login(username, password, code)
		time.sleep(3)
		# 登录成功的用例
		if is_success:
		self.assertIn(expect, self.driver.title)
		else:
		# 获取提示框消息
		msg = utils.get_tips_msg()
		print("msg=", msg)
		self.assertIn(expect, msg)

Junit参数化

------------------------------------------------------
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void test_ValueSource(int i) {
	System.out.println(i);
}
------------------------------------------------------
@ParameterizedTest
@EnumSource(ElementType.class)
void test_EnumSource(ElementType et) {
	System.out.println(et);
}
------------------------------------------------------
@ParameterizedTest
@EnumSource(value = ElementType.class, names = { "TYPE", "METHOD", "FIELD" })//如果只需要Enum中的特定值,则可以使用EnumSource name参数来实现。
void test_EnumSource_Extended(ElementType et) {
	assertTrue(EnumSet.of(ElementType.FIELD, ElementType.TYPE, ElementType.METHOD).contains(et));
}
------------------------------------------------------
@ParameterizedTest
@MethodSource("ms")
void test_MethodSource(String s) {
	assertNotNull(s);
}
static Stream<String> ms() {
	return Stream.of("A", "B");
}
------------------------------------------------------

@ParameterizedTest
@CsvSource(delimiter='|', value= {"1|'A'","2|B"})
void test_CsvSource(int i, String s) {
	assertTrue(3 > i);
	assertTrue(Arrays.asList("A", "B", "C").contains(s));
}
-----------------------------------------------------
@ParameterizedTest
@CsvFileSource(resources = "/country_code.csv", numLinesToSkip = 1)
void test_CsvFileSource(String country, int code) {
    assertNotNull(country);
    assertTrue(0 < code);
}
------------------------------------------------------

SpringBoot

(1)常用注解

  • 引导类:
    • @SpringBootApplication
      • @SpringBootConfiguration
      • @EnableAutoConfiguration
      • @ComponentScan
  • 表现层:
    • @RestController
      • @ResponseBody
      • @Controller
    • @RequestMapping
      • @PostMapping
      • @PutMapping
      • @PostMapping(“/status/0”)
      • @DeleteMapping
    • @Autowired
  • 业务层:
    • @Service
  • 数据层;
    • @Mapper
  • 全局异常处理;
    • @ControllerAdvice(annotations = {RestController.class, Controller.class})//表示这是一个aop通知类,做功能增强。
    • @ResponseBody//类中方法返回值将以JSON格式返回给前端。

(2)如何实现分页功能

  • 为了使用Mybatis-plus提供的分页接口,由于mybatis-plus基于AOP思想仅仅只是对mybatis功能进行增强,因此需要使用分页拦截器,拦截所有查询请求,并使用代理的方式,使用Mybatis-plus提供的接口完成自动分页功能。(mybatis-plus将会注入MybatisPlusInterceptor类型对象,如果没有添加任何拦截器,将不会拦截任何请求)
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

@RestController
@RequestMapping("/employee")
@Slf4j
public class EmployeeController {
    @Autowired
    private IEmployeeService employeeService;
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name){
        log.info("page = {},pageSize = {},name = {}" ,page,pageSize,name);
        //创建一个分页构造器,使用mybatisplus提供的实体。
        Page pageInfo = new Page(page,pageSize);
        //创建一个条件构造器
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
        //添加过滤条件,使用带bool类型的lambda表达式。
        queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
        //添加排序条件
        queryWrapper.orderByDesc(Employee::getUpdate_time);
        //执行查询
        employeeService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
  • 总结:
    • 构造一个MybatisPlus分页拦截器,交给SpringBoot管理。
    • 创建一个MybatisPlus提供的分页构造器。
    • 创建一个MybatisPlus提供的条件构造器,然后添加条件。
    • 调用MybatisPlus提供的接口page执行查询。
    • 返回分页构造器Records中存储着我们想要的分页数据。

(3)解决跨域问题

  • 当前浏览器加载页面的URL与当前页面请求的URL不一致(协议/域名/端口不同)。
  • 使用@CossOringe解决,一般加载表现层。

(4)MybatisPlus常用注解

  • @TableId
  • @TableField
  • @TableLogic
  • @Version
  • @OrderBy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值