Skip to content

Commit

Permalink
Add SimpleValueJqwikPlugin for beginners (#980)
Browse files Browse the repository at this point in the history
  • Loading branch information
seongahjo committed May 17, 2024
1 parent d7cc0fe commit abd262c
Show file tree
Hide file tree
Showing 9 changed files with 656 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: "Simple Value 플러그인"
images: []
menu:
docs:
parent: "plugins"
identifier: "simple-value-plugin"
weight: 50
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: "기능"
images: []
menu:
docs:
parent: "simple-value-plugin"
identifier: "simple-value-plugin-features"
weight: 51
---

픽스쳐 몽키는 엣지 케이스를 포함한 임의의 값을 생성합니다. 완전히 임의의 값을 생성하기 때문에 읽을 수 없는 데이터나 인코딩/디코딩 문제로 테스트를 깨트리는 데이터를 생성하기도 합니다.
이러한 특성은 발견하기 어려운 테스트 케이스를 검증하는데 도움을 주지만, 정밀한 제어가 요구됩니다. 특히 픽스처 몽키에 익숙하지 않은 사용자들은 이러한 특성이 테스트 코드 관리에 어려움을 느낄 수 있습니다.

이런 사용자들을 위해 픽스쳐 몽키는 `SimpleValueJqwikPlugin` 이라는 플러그인을 새로 만들었습니다. 이 플러그인은 읽을 수 있고 극단적이지 않은 값을 생성해주는 플러그인입니다.
플러그인이 변경하는 타입은 **문자열**, **숫자**, **날짜**, **컨테이너**입니다.

이 플러그인은 다른 플러그인, 특히 `JavaxValidationPlugin`, `JakartaValidationPlugin` 같은 플러그인과도 같이 사용할 수 있습니다.
JSR-380 어노테이션이 있는 프로퍼티는 `XXValidationPlugin`을 적용하고 어노테이션이 없는 프로퍼티는 `SimpleValueJqwikPlugin`을 적용합니다.

만약 값을 제한하는 플러그인을 만들어서 사용하신다면 가장 마지막에 등록한 플러그인이 우선순위를 가집니다.

값을 제한하는 플러그인을 만들고 싶은데 방법을 모르신다면 `SimpleValueJqwikPlugin`의 코드를 보시는 걸 추천합니다.

## 기본 값
### String
이 플러그인은 길이가 0부터 5까지인 문자열을 생성합니다. 생성하는 문자열은 아래와 같은 분류로 정리할 수 있습니다.

- 알파벳
- 숫자
- HTTP 쿼리 파라미터로 사용 가능한 특수문자들 `.`, `-`, `_`, `~`

다음 옵션을 사용해서 변경할 수 있습니다.
- minStringLength
- maxStringLength
- characterPredicate

### Number
이 플러그인은 -10000부터 10000의 범위를 가지는 **정수****실수**를 생성합니다.

다음 옵션을 사용해서 변경할 수 있습니다.
- minNumberValue
- maxNumberValue

### Date
이 플러그인은 작년부터 내년까지 범위를 가지는 **날짜**를 생성합니다.

다음 옵션을 사용해서 변경할 수 있습니다. 일 단위로 변경 가능합니다.
- minusDaysFromToday
- plusDaysFromToday

### Container
`Container`라는 용어는 Collection 인터페이스의 구현체 `List`, `Set`, `Iterator`, `Iterable``Map`, `Entry` 등을 의미합니다.

이 플러그인은 0개부터 3개의 요소를 가지는 컨테이너를 생성합니다.

다음 옵션을 사용해서 변경할 수 있습니다.
- minContainerSize
- maxContainerSize

## Plugin
```kotlin
val fixtureMonkey = FixtureMonkey.builder()
.plugin(SimpleValueJqwikPlugin())
.build()
```
3 changes: 3 additions & 0 deletions docs/content/v1.0.x-kor/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Modify the way a value class is used to output arbitrary value.

Fix `sealedInterface` set not working after thenApply.

Add a new Plugin `SimpleValueJqwikPlugin` for beginners, it provides a readable String, limited scope of Number and
Date. It can customize them as well.

sectionEnd

sectionStart
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: "Simple Value Plugin"
images: []
menu:
docs:
parent: "plugins"
identifier: "simple-value-plugin"
weight: 50
---
67 changes: 67 additions & 0 deletions docs/content/v1.0.x/docs/plugins/simple-value-plugin/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: "Features"
images: []
menu:
docs:
parent: "simple-value-plugin"
identifier: "simple-value-plugin-features"
weight: 51
---

Fixture Monkey generates an arbitrary value to avoid edge case that could cause the problem.
It may be useful in some situations, but it is useless in most situations.
Especially it is embarrassing for beginners, who expect the readable and valid data.

Fixture Monkey provides a new Plugin `SimpleValueJqwikPlugin` for beginners, who expect the readable and valid value.
It generates a readable and short String and narrow range of Number and Date value.

It is compatible with other plugins such as `JavaxValidationPlugin`, `JakartaValidationPlugin`.
It applies `XXValidationPlugin` if the property has the validation annotation, applies `SimpleValueJqwikPlugin` without it.

If you use the custom Plugin to constrain the generated value, the latter plugin would work.

For beginners who want to restrict the generated value, looking at the code of `SimpleValueJqwikPlugin` is a good start.

## Default value
### String
The plugin generates a short size of limited String whose length is 0 to 5.

- alphabet
- number
- some special symbols allowed in HTTP query parameter `.`, `-`, `_`, `~`

It can be customised by the options below.
- minStringLength
- maxStringLength
- characterPredicate

### Number
The plugin generates a numeric number and decimal number in the range -10000 to 10000.

It can be customised, whether negative or positive, using the options below.

- minNumberValue
- maxNumberValue

### Date
The plugin generates a Date in the range of last year to next year from today.

It can be customised on a per date basis, using the options below.

- minusDaysFromToday
- plusDaysFromToday

### Container
The term of `Container` refers to the implementations of Collection such as `List`, `Set`, `Iterator` `Iterable`, and `Map`, `Entry`.
The plugin generates a Container whose size is in the range of 0 to 3.

It can be customised by the options below.
- minContainerSize
- maxContainerSize

## Plugin
```kotlin
val fixtureMonkey = FixtureMonkey.builder()
.plugin(SimpleValueJqwikPlugin())
.build()
```
3 changes: 3 additions & 0 deletions docs/content/v1.0.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Modify the way a value class is used to output arbitrary value.

Fix `sealedInterface` set not working after thenApply.

Add a new Plugin `SimpleValueJqwikPlugin` for beginners, it provides a readable String, limited scope of Number and
Date. It can customize them as well.

sectionEnd

sectionStart
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.api.constraint;

import java.util.List;

import javax.annotation.Nullable;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext;

@API(since = "1.0.17", status = Status.EXPERIMENTAL)
public final class CompositeJavaConstraintGenerator implements JavaConstraintGenerator {
private final List<JavaConstraintGenerator> javaConstraintGenerators;

public CompositeJavaConstraintGenerator(List<JavaConstraintGenerator> javaConstraintGenerators) {
this.javaConstraintGenerators = javaConstraintGenerators;
}

@Nullable
@Override
public JavaStringConstraint generateStringConstraint(ArbitraryGeneratorContext context) {
for (JavaConstraintGenerator javaConstraintGenerator : javaConstraintGenerators) {
JavaStringConstraint constraint = javaConstraintGenerator.generateStringConstraint(context);
if (constraint != null) {
return constraint;
}
}
return null;
}

@Nullable
@Override
public JavaIntegerConstraint generateIntegerConstraint(ArbitraryGeneratorContext context) {
for (JavaConstraintGenerator javaConstraintGenerator : javaConstraintGenerators) {
JavaIntegerConstraint constraint = javaConstraintGenerator.generateIntegerConstraint(context);
if (constraint != null) {
return constraint;
}
}
return null;
}

@Nullable
@Override
public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext context) {
for (JavaConstraintGenerator javaConstraintGenerator : javaConstraintGenerators) {
JavaDecimalConstraint constraint = javaConstraintGenerator.generateDecimalConstraint(context);
if (constraint != null) {
return constraint;
}
}
return null;
}

@Nullable
@Override
public JavaContainerConstraint generateContainerConstraint(ArbitraryGeneratorContext context) {
for (JavaConstraintGenerator javaConstraintGenerator : javaConstraintGenerators) {
JavaContainerConstraint constraint = javaConstraintGenerator.generateContainerConstraint(context);
if (constraint != null) {
return constraint;
}
}
return null;
}

@Nullable
@Override
public JavaDateTimeConstraint generateDateTimeConstraint(ArbitraryGeneratorContext context) {
for (JavaConstraintGenerator javaConstraintGenerator : javaConstraintGenerators) {
JavaDateTimeConstraint constraint = javaConstraintGenerator.generateDateTimeConstraint(context);
if (constraint != null) {
return constraint;
}
}
return null;
}
}

0 comments on commit abd262c

Please sign in to comment.