javafaker测试数据生成实战
- 1.背景
- 2.介绍
- 2.1 特点
- 3. 使用
- 3.1 基础使用
- 3.1.1 maven依赖
- 3.1.1 使用示例
- 3.2 进阶使用
- 3.1 生成中文信息
- 3.2 根据姓名生成账号
- 3.2.1 maven依赖
- 3.2.2 中文转拼音工具类
- 3.3 高级使用
- 3.3.1 中文性名重复处理
- 方案1: 偷懒方式
- 方案2: 较真模式
1.背景
最近需要测试mysql的json字段的相关性能如查询性能,需要大量数据场景下验证,比如100万条信息。本来要自己造,但是不够真实写起来挺麻烦。笔者是懒人,研究下了JavaFaker 可以正好满足场景,本文总结下使用用法,及碰到一些不满足要求场景的解决方案
需要造数据如下:
字段名 | 说明 |
---|---|
name | 姓名 |
username | 用户名 |
address | 地址 |
email | 电子邮件地址 |
phoneNumber | 手机号码 |
date | 生日日期 |
scope | 范围 |
password | 密码 |
ipAddress | IPv4地址 |
bloodGroup | 血型 |
2.介绍
JavaFaker 是一个用于生成假数据(例如姓名、地址、电子邮件、日期等)的Java库。它可以帮助开发人员在开发和测试过程中生成真实和随机的数据,而不必依赖于真实的数据集。以下是 JavaFaker 的主要特点和用法:
2.1 特点
-
多语言支持: JavaFaker 支持多种语言,包括英语、中文、法语、德语等。
-
丰富的数据类型: JavaFaker 可以生成各种类型的假数据,包括姓名、地址、电子邮件、日期、电话号码、公司名称、文本段落等。
-
随机性和真实性: 生成的数据是随机的,但是符合真实世界的模式和格式,使得生成的数据看起来更真实。
-
可自定义: 可以通过扩展和自定义来满足特定需求,例如自定义国家、姓氏、名字等。
3. 使用
3.1 基础使用
3.1.1 maven依赖
<!--随机生成测试数据-->
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
3.1.1 使用示例
import com.github.javafaker.Faker;
public class JavaFakerBaseTest {
public static void main(String[] args) {
Faker faker = new Faker(); // 默认语言为英语
// 生成随机姓名、地址、电子邮件等
String name = faker.name().fullName();
String address = faker.address().fullAddress();
String email = faker.internet().emailAddress();
String phoneNumber = faker.phoneNumber().cellPhone();
String date = faker.date().birthday().toString();
// 输出生成的数据
System.out.println("姓名: " + name);
System.out.println("地址: " + address);
System.out.println("邮箱: " + email);
System.out.println("电话号码: " + phoneNumber);
System.out.println("生日: " + date);
}
}
效果:
3.2 进阶使用
3.1 生成中文信息
Faker faker = new Faker(new Locale(“zh”, “CN”)); // 设置语言为简体中文
public class JavaFakerTest {
public static void main(String[] args) {
Faker faker = new Faker(new Locale("zh", "CN")); // 设置语言为简体中文
for (int i = 0; i < 100; i++) { // 生成10个随机中文名字
String name = faker.name().fullName(); // 随机生成姓名
String address = faker.address().fullAddress(); // 随机生成地址
// String email = faker.internet().emailAddress(); // 随机生成电子邮件地址
//String username = PinyinUtils.convertToPinyin(name);
String email = faker.internet().emailAddress(username);
String phoneNumber = faker.phoneNumber().cellPhone(); // 随机生成手机号码
Date date = faker.date().birthday(); // 随机生成生日日期
int scope = faker.number().numberBetween(1, 100); // 在指定范围内生成随机整数
String password = faker.internet().password(8, 9, true); // 随机生成密码
String ipAddress = faker.internet().ipV4Address(); // 随机生成IPv4地址
String bloodGroup = faker.name().bloodGroup(); //随机生成血型
// 打印生成的随机数据,使用制表符分隔
System.out.println(name + "\t" + username + "\t" + address + "\t" + email + "\t" + phoneNumber + "\t" + date + "\t" + scope + "\t" + password + "\t" + ipAddress + "\t" + bloodGroup);
}
}
}
3.2 根据姓名生成账号
根据用户名生成拼音作为用户的用户名。 需要借助pinyin4j 来实现
3.2.1 maven依赖
<!--汉字转拼音-->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
3.2.2 中文转拼音工具类
/**
* 依赖如下
* <dependency>
* <groupId>com.belerweb</groupId>
* <artifactId>pinyin4j</artifactId>
* <version>2.5.1</version>
* </dependency>
*/
public class PinyinUtils {
private static final HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
static {
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
}
/**
* 将中文字符串转换为拼音
*
* @param chinese 中文字符串
* @return 拼音字符串,如果无法转换返回空字符串
*/
public static String convertToPinyin(String chinese) {
StringBuilder pinyinBuilder = new StringBuilder();
for (char ch : chinese.toCharArray()) {
// 判断是否为汉字字符
if (Character.toString(ch).matches("[\\u4E00-\\u9FA5]+")) {
try {
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format);
if (pinyinArray != null && pinyinArray.length > 0) {
// 多音字只取第一个拼音
pinyinBuilder.append(pinyinArray[0]);
}
} catch (Exception e) {
// 异常时保持原样
pinyinBuilder.append(ch);
}
} else {
// 非汉字字符保持原样
pinyinBuilder.append(ch);
}
}
return pinyinBuilder.toString();
}
public static void main(String[] args) {
String chineseName = "张三"; // 中文名字
String pinyin = PinyinUtils.convertToPinyin(chineseName);
System.out.println("拼音: " + pinyin);
}
}
- 效果
3.3 高级使用
3.3.1 中文性名重复处理
在实际使用测试数据导入,数据库中,当循环生成测试数据,当数据量较大时候(一万多条时候). 会出现性名重复情况。虽然姓名重复,在现实存在, name可以重复,但是username用来用户登录唯一标识,肯定需要唯一性。
方案1: 偷懒方式
重复username使用累计编号,使用先来后到重名就加一。如: zhangsan -> zhangsan1
- 先获取所有用户名
- 判断如果重复则在根据name生成的username加序号
@Service
public class AccountServiceImpl implements AccountService {
private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);
@Autowired
private AccountMapper accountMapper;
private Faker faker = new Faker(new Locale("zh", "CN")); // 设置语言为简体中文
public void batchInitAccount(int count) {
List<Object> allUsername = listAllUsername();
Faker faker = new Faker(new Locale("zh", "CN")); // 设置语言为简体中文
for (int i = 0; i < count; i++) {
String name = faker.name().fullName(); // 随机生成姓名
String username = PinyinUtils.convertToPinyin(name);
// 名字重复继续生成
int num = 1;
while (allUsername.contains(username)) {
username = PinyinUtils.convertToPinyin(name) + num ++;
}
allUsername.add(username);
String address = faker.address().fullAddress(); // 随机生成地址
// String email = faker.internet().emailAddress(); // 随机生成电子邮件地址
String email = faker.internet().emailAddress(username);
String phoneNumber = faker.phoneNumber().cellPhone(); // 随机生成手机号码
Date date = faker.date().birthday(); // 随机生成生日日期
int scope = faker.number().numberBetween(1, 100); // 在指定范围内生成随机整数
String password = faker.internet().password(8, 9, true); // 随机生成密码
String ipAddress = faker.internet().ipV4Address(); // 随机生成IPv4地址
String bloodGroup = faker.name().bloodGroup(); //随机生成血型
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
account.setName(name);
account.setPhone(phoneNumber);
account.setEmail(email);
account.setCreateTime(date);
JSONObject extendJson = new JSONObject();
extendJson.put("address", address);
extendJson.put("scope", scope);
extendJson.put("ip", ipAddress);
extendJson.put("bloodGroup", bloodGroup);
account.setExtendJson(extendJson);
try {
this.accountMapper.insert(account);
System.out.println(account.getId());
} catch (Exception e) {
// e.printStackTrace();
// 名字重复忽略
LOGGER.error("名字重复");
}
}
}
}
方案2: 较真模式
TODO