Skip to content

Commit 54771f7

Browse files
tabledata: add withNewKeyColumns (#732)
1 parent 33aa4dc commit 54771f7

8 files changed

Lines changed: 156 additions & 15 deletions

File tree

webtau-core-groovy/src/test/groovy/org/testingisdocumenting/webtau/data/table/TableDataGroovyTest.groovy

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,35 @@ class TableDataGroovyTest {
9393
validateSimpleTableDataAfterReplace(newTableData)
9494
}
9595

96+
@Test
97+
void "access by key column"() {
98+
TableData tableData = createTableWithKeyColumns()
99+
findByKeyAndValidate(tableData)
100+
}
101+
102+
@Test
103+
void "should change key columns and validate uniqueness"() {
104+
def tableData = createTableWithKeyColumns()
105+
code {
106+
changeKeyColumns(tableData)
107+
} should throwException("duplicate entry found with key: [N, T]\n" +
108+
"{id=id1, Name=N, Type=T}\n" +
109+
"{id=id3, Name=N, Type=T}")
110+
}
111+
96112
private static TableData replaceValue(TableData tableData) {
97113
tableData.replace("v1b", "v1b_")
98114
}
99115

116+
private static TableData changeKeyColumns(TableData tableData) {
117+
tableData.withNewKeyColumns("Name", "Type")
118+
}
119+
120+
private static void findByKeyAndValidate(TableData tableData) {
121+
def found = tableData.find(key("id2"))
122+
found.Name.should == "N2"
123+
}
124+
100125
@Test
101126
void "should ignore underscore under header"() {
102127
def table = ["hello" | "world"] {
@@ -162,4 +187,12 @@ class TableDataGroovyTest {
162187
"Bob" | cell.above | increment
163188
"Mike" | cell.above | increment }
164189
}
190+
191+
static TableData createTableWithKeyColumns() {
192+
["*id" | "Name" | "Type"] {
193+
___________________________
194+
"id1" | "N" | "T"
195+
"id2" | "N2" | "T2"
196+
"id3" | "N" | "T" }
197+
}
165198
}

webtau-core/src/main/java/org/testingisdocumenting/webtau/WebTauCore.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.testingisdocumenting.webtau.data.table.TableData;
2222
import org.testingisdocumenting.webtau.data.table.TableDataUnderscore;
2323
import org.testingisdocumenting.webtau.data.table.autogen.TableDataCellValueGenFunctions;
24+
import org.testingisdocumenting.webtau.data.table.header.CompositeKey;
2425
import org.testingisdocumenting.webtau.documentation.CoreDocumentation;
2526
import org.testingisdocumenting.webtau.expectation.ActualPath;
2627
import org.testingisdocumenting.webtau.persona.Persona;
@@ -50,6 +51,10 @@ public static TableData table(Object... columnNames) {
5051
return new TableData(Arrays.stream(columnNames));
5152
}
5253

54+
public static CompositeKey key(Object... values) {
55+
return new CompositeKey(Arrays.stream(values));
56+
}
57+
5358
public static MultiValue permute(Object atLeastOneValue, Object... values) {
5459
return new MultiValue(atLeastOneValue, values);
5560
}

webtau-core/src/main/java/org/testingisdocumenting/webtau/data/table/TableData.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,23 @@ public Integer findRowIdxByKey(CompositeKey key) {
7070
return rowIdxByKey.get(key);
7171
}
7272

73+
/**
74+
* create new table data with the data of a current one but with new key columns.
75+
* can be used to validate new key columns uniqueness
76+
* @param keyColumns new key columns
77+
* @return new table data with updated key columns
78+
*/
79+
public TableData withNewKeyColumns(String... keyColumns) {
80+
TableDataHeader newHeader = new TableDataHeader(header.getNamesStream(), Arrays.stream(keyColumns));
81+
TableData withNewHeader = new TableData(newHeader);
82+
83+
for (Record originalRow : rows) {
84+
withNewHeader.addRow(newHeader.createRecord(originalRow.valuesStream()));
85+
}
86+
87+
return withNewHeader;
88+
}
89+
7390
/**
7491
* @param values row values combined in one vararg
7592
* @return populate table data instance

webtau-core/src/main/java/org/testingisdocumenting/webtau/data/table/header/CompositeKey.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/*
2+
* Copyright 2020 webtau maintainers
23
* Copyright 2019 TWO SIGMA OPEN SOURCE, LLC
34
*
45
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,7 +28,7 @@
2728
* Composite key to be used in structures like {@link TableData}.
2829
*/
2930
public class CompositeKey {
30-
private List<Object> values;
31+
private final List<Object> values;
3132

3233
public CompositeKey(Stream<Object> values) {
3334
this.values = values

webtau-core/src/main/java/org/testingisdocumenting/webtau/data/table/header/TableDataHeader.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,29 @@
1919

2020
import org.testingisdocumenting.webtau.data.table.Record;
2121

22-
import java.util.ArrayList;
23-
import java.util.HashMap;
24-
import java.util.List;
25-
import java.util.Map;
22+
import java.util.*;
23+
import java.util.stream.Collectors;
2624
import java.util.stream.IntStream;
2725
import java.util.stream.Stream;
2826

2927
public class TableDataHeader {
30-
private final Map<String, Integer> indexByName;
31-
private final List<String> namesByIndex;
28+
private final Map<String, Integer> indexByName = new HashMap<>();
29+
private final List<String> namesByIndex = new ArrayList<>();
3230

31+
private final List<Integer> keyIdx = new ArrayList<>();
3332
private final List<String> keyNames;
34-
private final List<Integer> keyIdx;
3533

3634
public TableDataHeader(Stream<String> names) {
37-
this.indexByName = new HashMap<>();
38-
this.namesByIndex = new ArrayList<>();
3935
this.keyNames = new ArrayList<>();
40-
this.keyIdx = new ArrayList<>();
41-
4236
names.forEach(this::add);
4337
}
4438

39+
public TableDataHeader(Stream<String> names, Stream<String> keyNames) {
40+
this.keyNames = new ArrayList<>();
41+
Set<String> keyNamesAsSet = keyNames.collect(Collectors.toSet());
42+
names.forEach(name -> add(name, keyNamesAsSet.contains(name)));
43+
}
44+
4545
public Record createRecord(Stream<Object> values) {
4646
return new Record(this, values);
4747
}
@@ -82,9 +82,13 @@ private void add(String nameWithMeta) {
8282
boolean startsWithAsterisk = nameWithMeta.startsWith("*");
8383

8484
String name = startsWithAsterisk ? nameWithMeta.substring(1) : nameWithMeta;
85+
add(name, startsWithAsterisk);
86+
}
87+
88+
private void add(String name, boolean isKeyColumn) {
8589
int newIdx = namesByIndex.size();
8690

87-
if (startsWithAsterisk) {
91+
if (isKeyColumn) {
8892
keyNames.add(name);
8993
keyIdx.add(newIdx);
9094
}
@@ -95,6 +99,7 @@ private void add(String nameWithMeta) {
9599
}
96100

97101
namesByIndex.add(name);
102+
98103
}
99104

100105
public String columnNameByIdx(int idx) {

webtau-core/src/test/groovy/org/testingisdocumenting/webtau/data/table/TableDataHeaderTest.groovy

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class TableDataHeaderTest {
4040

4141
@Test
4242
void "defines key columns using asterisk in front of column name"() {
43-
assert header.getKeyNamesStream().collect(toList()) == ["ColumnB", "ColumnC"]
44-
assert header.getKeyIdxStream().collect(toList()) == [1, 2]
43+
assert header.keyNamesStream.collect(toList()) == ["ColumnB", "ColumnC"]
44+
assert header.keyIdxStream.collect(toList()) == [1, 2]
4545
}
4646

4747
@Test
@@ -51,4 +51,15 @@ class TableDataHeaderTest {
5151
def keyLessHeader = new TableDataHeader(Stream.of("ColumnA", "ColumnB"))
5252
assert ! keyLessHeader.hasKeyColumns()
5353
}
54+
55+
@Test
56+
void "define key columns as a second parameter to constructor"() {
57+
def header = new TableDataHeader(Stream.of("ColumnA", "ColumnB", "ColumnC", "ColumnD"),
58+
Stream.of("ColumnB", "ColumnC"))
59+
60+
assert header.columnIdxByName("ColumnB") == 1
61+
assert header.has("ColumnC")
62+
assert header.keyNamesStream.collect(toList()) == ["ColumnB", "ColumnC"]
63+
assert header.keyIdxStream.collect(toList()) == [1, 2]
64+
}
5465
}

webtau-core/src/test/java/org/testingisdocumenting/webtau/data/table/TableDataJavaTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.time.LocalDate;
2525
import java.time.format.DateTimeFormatter;
2626

27+
import static org.testingisdocumenting.webtau.Matchers.code;
2728
import static org.testingisdocumenting.webtau.WebTauCore.*;
2829
import static org.testingisdocumenting.webtau.data.table.TableDataJavaTestValidations.*;
2930

@@ -98,10 +99,36 @@ public void shouldReplaceSingleSpecifiedValue() {
9899
saveTableWithDate(newTableData, "table-after-replace");
99100
}
100101

102+
@Test
103+
public void accessByKeyColumn() {
104+
TableData tableData = createTableWithKeyColumns();
105+
findByKeyAndValidate(tableData);
106+
}
107+
108+
@Test
109+
public void shouldChangeKeyColumnsAndValidateUniqueness() {
110+
TableData tableData = createTableWithKeyColumns();
111+
112+
code(() ->
113+
changeKeyColumns(tableData)
114+
).should(throwException("duplicate entry found with key: [N, T]\n" +
115+
"{id=id1, Name=N, Type=T}\n" +
116+
"{id=id3, Name=N, Type=T}"));
117+
}
118+
101119
private static TableData replaceValue(TableData tableData) {
102120
return tableData.replace("v1b", "v1b_");
103121
}
104122

123+
private static TableData changeKeyColumns(TableData tableData) {
124+
return tableData.withNewKeyColumns("Name", "Type");
125+
}
126+
127+
private static void findByKeyAndValidate(TableData tableData) {
128+
Record found = tableData.find(key("id2"));
129+
actual(found.get("Name")).should(equal("N2"));
130+
}
131+
105132
private static TableData createTableDataSeparateValues() {
106133
return table("Col A", "Col B", "Col C").values(
107134
"v1a", "v1b", "v1c",
@@ -161,6 +188,14 @@ private static TableData createTableDataWithAboveRefAndMathExtracted() {
161188
"Mike", cell.above , increment);
162189
}
163190

191+
static TableData createTableWithKeyColumns() {
192+
return table("*id" , "Name" , "Type",
193+
_______________________,
194+
"id1" , "N" , "T",
195+
"id2" , "N2" , "T2",
196+
"id3" , "N" , "T");
197+
}
198+
164199
private void saveTableWithDate(TableData tableData, String artifactName) {
165200
DocumentationArtifacts.createAsJson(TableDataJavaTest.class, artifactName,
166201
tableData

webtau-docs/znai/reference/table-data.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,40 @@ Java:
2424
:include-java: org/testingisdocumenting/webtau/data/table/TableDataJavaTest.java {entry: "createTableDataSeparateValues", bodyOnly: true, removeReturn: true, removeSemicolon: true}
2525
```
2626

27+
# Key Columns
28+
29+
Use `*` in front of a column to specify it as a key column
30+
31+
```tabs
32+
Groovy:
33+
:include-groovy: org/testingisdocumenting/webtau/data/table/TableDataGroovyTest.groovy {entry: "createTableWithKeyColumns", bodyOnly: true}
34+
35+
Java:
36+
:include-java: org/testingisdocumenting/webtau/data/table/TableDataJavaTest.java {entry: "createTableWithKeyColumns", bodyOnly: true, removeReturn: true, removeSemicolon: true}
37+
```
38+
39+
To access a value by key column
40+
41+
```tabs
42+
Groovy:
43+
:include-groovy: org/testingisdocumenting/webtau/data/table/TableDataGroovyTest.groovy {entry: "findByKeyAndValidate", bodyOnly: true}
44+
45+
Java:
46+
:include-java: org/testingisdocumenting/webtau/data/table/TableDataJavaTest.java {entry: "findByKeyAndValidate", bodyOnly: true}
47+
```
48+
49+
To change key columns of an existing table
50+
51+
```tabs
52+
Groovy:
53+
:include-groovy: org/testingisdocumenting/webtau/data/table/TableDataGroovyTest.groovy {entry: "changeKeyColumns", bodyOnly: true}
54+
55+
Java:
56+
:include-java: org/testingisdocumenting/webtau/data/table/TableDataJavaTest.java {entry: "changeKeyColumns", bodyOnly: true, removeReturn: true, removeSemicolon: true}
57+
```
58+
59+
Note: `withNewKeyColumns` creates new table and validates new key column uniqueness
60+
2761
# Permutations
2862

2963
Use `permute(v1, v2)` to automatically generate multiple rows.

0 commit comments

Comments
 (0)