Skip to content

Commit fd5489d

Browse files
committed
Maven project tests
Signed-off-by: Piotr Nestorow <piotr.nestorow@systemverification.com>
1 parent 24817da commit fd5489d

File tree

8 files changed

+325
-0
lines changed

8 files changed

+325
-0
lines changed

test/maven.test.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import * as assert from 'assert';
2+
import * as child_process from 'child_process';
3+
import { join } from 'path';
4+
import { platform } from 'os';
5+
import { createSandbox, SinonSandbox } from 'sinon';
6+
import { CLI } from '../src/cli';
7+
import { MAVEN_COMMAND } from '../src/constants';
8+
import { buildRunArgs } from '../src/execution/runArgs';
9+
10+
suite('CLI.getCommand MAVEN_COMMAND', () => {
11+
let sandbox: SinonSandbox;
12+
13+
setup(() => {
14+
sandbox = createSandbox();
15+
});
16+
17+
teardown(() => {
18+
sandbox.restore();
19+
});
20+
21+
test('returns correct mvn command string', () => {
22+
// Stub spawnSync to simulate command resolution based on platform.
23+
sandbox.stub(child_process, 'spawnSync').callsFake(
24+
(command: string, args?: readonly string[], options?: child_process.SpawnSyncOptions) => {
25+
const successResult = {
26+
pid: 1234,
27+
output: [ '', Buffer.from(''), Buffer.from('') ],
28+
stdout: Buffer.from(''),
29+
stderr: Buffer.from(''),
30+
status: 0,
31+
signal: null,
32+
error: null
33+
};
34+
35+
const failureResult = {
36+
pid: 1234,
37+
output: [ '', Buffer.from(''), Buffer.from('') ],
38+
stdout: Buffer.from(''),
39+
stderr: Buffer.from(''),
40+
status: 1,
41+
signal: null,
42+
error: new Error('command not found')
43+
};
44+
45+
if (platform() === 'win32') {
46+
// On Windows, only "mvn.cmd" should succeed.
47+
return command === `${MAVEN_COMMAND}.cmd` ? successResult : failureResult;
48+
} else {
49+
// On non-Windows, only "mvn" should succeed.
50+
return command === MAVEN_COMMAND ? successResult : failureResult;
51+
}
52+
}
53+
);
54+
55+
const actual = (CLI as any).getCommand(MAVEN_COMMAND);
56+
if (platform() === 'win32') {
57+
assert.strictEqual(actual, `${MAVEN_COMMAND}.cmd`);
58+
} else {
59+
assert.strictEqual(actual, MAVEN_COMMAND);
60+
}
61+
});
62+
});
63+
64+
suite('Actual Gauge Run Spec Execution', () => {
65+
66+
test('executes "Run Spec" for a maven project via Maven args and verifies output', function () {
67+
// Increase timeout for long-running processes.
68+
this.timeout(15000);
69+
70+
// Adjust projectRoot correctly from the compiled out directory to the source testdata folder.
71+
const projectRoot = join(__dirname, '..', '..', 'test', 'testdata', 'mavenProject');
72+
// Use a relative path for the spec file so that -DspecsDir is set to "specs"
73+
const specFile = join('specs', 'example.spec');
74+
75+
// Build the Maven arguments using the extension’s runArgs logic.
76+
// With a relative spec, buildMavenArgs should produce -DspecsDir=specs.
77+
const args = buildRunArgs.forMaven(specFile, {}); // Use default options
78+
79+
// Get the Maven command (mvn or mvn.cmd) from the CLI.
80+
const mavenCmd = (CLI as any).getCommand(MAVEN_COMMAND);
81+
82+
// Build the spawn options. Add shell: true on Windows.
83+
const spawnOptions: child_process.SpawnSyncOptions = {
84+
encoding: 'utf8',
85+
cwd: projectRoot
86+
};
87+
if (platform() === 'win32') {
88+
spawnOptions.shell = true;
89+
}
90+
91+
// Echo mavenCmd, args, and spawnOptions to the console.
92+
//console.log('mavenCmd:', mavenCmd);
93+
//console.log('args:', args);
94+
//console.log('spawnOptions:', spawnOptions);
95+
96+
// Spawn the Maven process with the constructed arguments.
97+
const result = child_process.spawnSync(mavenCmd, args, spawnOptions);
98+
99+
// If an error occurred during spawnSync, fail the test.
100+
if (result.error) {
101+
assert.fail(`Error executing maven run: ${result.error.message}`);
102+
}
103+
104+
// Verify that the process exited successfully.
105+
assert.strictEqual(result.status, 0, 'Process should exit with status 0');
106+
107+
// Verify that stdout contains the expected specification summary.
108+
const expectedSubstring = 'Specifications:\t1 executed\t1 passed\t0 failed\t0 skipped';
109+
assert.ok(
110+
result.stdout.includes(expectedSubstring),
111+
`Expected output to include "${expectedSubstring}".\nActual output:\n${result.stdout}`
112+
);
113+
});
114+
});

test/testdata/mavenProject/.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Gauge - metadata dir
2+
.gauge
3+
4+
# Gauge - log files dir
5+
logs
6+
7+
# Gauge - reports generated by reporting plugins
8+
reports
9+
10+
# Gauge - java class output directory
11+
gauge_bin
12+
13+
# Gauge - java class target dir
14+
target
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# default.properties
2+
# properties set here will be available to the test execution as environment variables
3+
4+
# sample_key = sample_value
5+
6+
# The path to the gauge reports directory. Should be either relative to the project directory or an absolute path
7+
gauge_reports_dir = reports
8+
9+
# Set as false if gauge reports should not be overwritten on each execution. A new time-stamped directory will be created on each execution.
10+
overwrite_reports = true
11+
12+
# Set to false to disable screenshots on failure in reports.
13+
screenshot_on_failure = true
14+
15+
# The path to the gauge logs directory. Should be either relative to the project directory or an absolute path
16+
logs_directory = logs
17+
18+
# Set to true to use multithreading for parallel execution
19+
enable_multithreading = false
20+
21+
# Possible values for this property are 'suite', 'spec' or 'scenario'.
22+
# 'scenario' clears the objects after the execution of each scenario, new objects are created for next execution.
23+
gauge_clear_state_level = scenario
24+
25+
# The path the gauge specifications directory. Takes a comma separated list of specification files/directories.
26+
gauge_specs_dir = specs
27+
28+
# The default delimiter used read csv files.
29+
csv_delimiter = ,
30+
31+
# Allows steps to be written in multiline
32+
allow_multiline_step = false
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
# Specify an alternate Java home if you want to use a custom version
3+
gauge_java_home =
4+
5+
# IntelliJ and Eclipse out directory will be usually autodetected
6+
# Use the below property if you need to override the build path
7+
gauge_custom_build_path =
8+
9+
# specify the directory where additional libs are kept
10+
# you can specify multiple directory names separated with a comma (,)
11+
gauge_additional_libs = libs/*
12+
13+
# JVM arguments passed to java while launching. Enter multiple values separated by comma (,) eg. Xmx1024m, Xms128m
14+
gauge_jvm_args =
15+
16+
# specify the directory containing java files to be compiled
17+
# you can specify multiple directory names separated with a comma (,)
18+
gauge_custom_compile_dir =
19+
20+
# specify the level at which the objects should be cleared
21+
# Possible values are suite, spec and scenario. Default value is scenario.
22+
gauge_clear_state_level = scenario
23+
24+
MAVEN_COMMAND = mvn.cmd
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"Language": "java",
3+
"Plugins": [
4+
"html-report"
5+
]
6+
}

test/testdata/mavenProject/pom.xml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>gauge_java_maven</groupId>
6+
<artifactId>gauge_java_maven</artifactId>
7+
<version>1.0-SNAPSHOT</version>
8+
9+
<dependencies>
10+
<dependency>
11+
<groupId>com.thoughtworks.gauge</groupId>
12+
<artifactId>gauge-java</artifactId>
13+
<version>0.11.2</version>
14+
<scope>test</scope>
15+
</dependency>
16+
<dependency>
17+
<groupId>org.assertj</groupId>
18+
<artifactId>assertj-core</artifactId>
19+
<version>3.17.2</version>
20+
<scope>test</scope>
21+
</dependency>
22+
</dependencies>
23+
24+
<build>
25+
<plugins>
26+
<plugin>
27+
<groupId>org.apache.maven.plugins</groupId>
28+
<artifactId>maven-compiler-plugin</artifactId>
29+
<configuration>
30+
<source>17</source>
31+
<target>17</target>
32+
</configuration>
33+
</plugin>
34+
<plugin>
35+
<groupId>com.thoughtworks.gauge.maven</groupId>
36+
<artifactId>gauge-maven-plugin</artifactId>
37+
<version>1.6.3</version>
38+
<executions>
39+
<execution>
40+
<phase>test</phase>
41+
<configuration>
42+
<specsDir>specs</specsDir>
43+
</configuration>
44+
<goals>
45+
<goal>execute</goal>
46+
</goals>
47+
</execution>
48+
</executions>
49+
</plugin>
50+
</plugins>
51+
</build>
52+
53+
</project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Specification Heading
2+
=====================
3+
4+
This is an executable specification file. This file follows markdown syntax.
5+
Every heading in this file denotes a scenario. Every bulleted point denotes a step.
6+
7+
To execute this specification, run
8+
gauge specs
9+
10+
11+
* Vowels in English language are "aeiou".
12+
13+
Vowel counts in single word
14+
---------------------------
15+
16+
tags: single word
17+
18+
* The word "gauge" has "3" vowels.
19+
20+
21+
Vowel counts in multiple word
22+
-----------------------------
23+
24+
This is the second scenario in this specification
25+
26+
Here's a step that takes a table
27+
28+
* Almost all words have vowels
29+
|Word |Vowel Count|
30+
|------|-----------|
31+
|Gauge |3 |
32+
|Mingle|2 |
33+
|Snap |1 |
34+
|GoCD |1 |
35+
|Rhythm|0 |
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import com.thoughtworks.gauge.Step;
2+
import com.thoughtworks.gauge.Table;
3+
import com.thoughtworks.gauge.TableRow;
4+
5+
import java.util.HashSet;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
public class StepImplementation {
10+
11+
private HashSet<Character> vowels;
12+
13+
@Step("Vowels in English language are <vowelString>.")
14+
public void setLanguageVowels(String vowelString) {
15+
vowels = new HashSet<>();
16+
for (char ch : vowelString.toCharArray()) {
17+
vowels.add(ch);
18+
}
19+
}
20+
21+
@Step("The word <word> has <expectedCount> vowels.")
22+
public void verifyVowelsCountInWord(String word, int expectedCount) {
23+
int actualCount = countVowels(word);
24+
assertThat(expectedCount).isEqualTo(actualCount);
25+
}
26+
27+
@Step("Almost all words have vowels <wordsTable>")
28+
public void verifyVowelsCountInMultipleWords(Table wordsTable) {
29+
for (TableRow row : wordsTable.getTableRows()) {
30+
String word = row.getCell("Word");
31+
int expectedCount = Integer.parseInt(row.getCell("Vowel Count"));
32+
int actualCount = countVowels(word);
33+
34+
assertThat(expectedCount).isEqualTo(actualCount);
35+
}
36+
}
37+
38+
private int countVowels(String word) {
39+
int count = 0;
40+
for (char ch : word.toCharArray()) {
41+
if (vowels.contains(ch)) {
42+
count++;
43+
}
44+
}
45+
return count;
46+
}
47+
}

0 commit comments

Comments
 (0)