chore: establish iteration 1 development baseline
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
25
|
||||||
@@ -1,2 +1,24 @@
|
|||||||
# labtimesheet
|
# Lab Timesheet
|
||||||
|
|
||||||
|
## Local development
|
||||||
|
|
||||||
|
The application targets Java 25 and expects PostgreSQL on
|
||||||
|
`localhost:55432` when the default `dev` profile is active. Override any local
|
||||||
|
value with `LAB_DB_URL`, `LAB_DB_USERNAME`, `LAB_DB_PASSWORD`,
|
||||||
|
`LAB_SMTP_HOST`, or `LAB_SMTP_PORT`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
|
||||||
|
export PATH="$JAVA_HOME/bin:$PATH"
|
||||||
|
./mvnw spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests use PostgreSQL 18.4 through Testcontainers and do not use the developer
|
||||||
|
database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./mvnw test
|
||||||
|
```
|
||||||
|
|
||||||
|
Every feature test must have a companion Markdown evidence record under
|
||||||
|
[`docs/tests`](docs/tests/README.md).
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Test Evidence
|
||||||
|
|
||||||
|
TDD is mandatory. Every feature test must have one companion Markdown record
|
||||||
|
in the directory matching its test type:
|
||||||
|
|
||||||
|
- `unit/` — isolated state, calculation, and domain behavior.
|
||||||
|
- `integration/` — PostgreSQL, Flyway, repository, transaction, and module integration.
|
||||||
|
- `web/` — MockMvc, Thymeleaf, validation, and security behavior.
|
||||||
|
- `e2e/` — cross-module, browser, or full user journeys.
|
||||||
|
|
||||||
|
Copy that directory's `_TEMPLATE.md` and keep every heading. One evidence file
|
||||||
|
may cover a cohesive parameterized scenario set, but it must name every
|
||||||
|
requirement and scenario ID it protects.
|
||||||
|
|
||||||
|
An evidence record is complete only when it contains the observed RED failure,
|
||||||
|
the observed GREEN result, the affected-suite result, and honest external-test
|
||||||
|
boundaries. Commands and relevant output are copied exactly; prose such as
|
||||||
|
"passed locally" is not evidence.
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Test Evidence: <short behavior name>
|
||||||
|
|
||||||
|
- **Test type:** E2E
|
||||||
|
- **Requirement IDs:** `<ID>`
|
||||||
|
- **Scenario IDs:** `<ID>`
|
||||||
|
- **Test class/method:** `<fully qualified class and method>`
|
||||||
|
- **Implementation commit:** `<short SHA or pending>`
|
||||||
|
|
||||||
|
## Protected behavior
|
||||||
|
|
||||||
|
<Externally observable rule and failure mode protected by this test.>
|
||||||
|
|
||||||
|
## Test method
|
||||||
|
|
||||||
|
<Setup, action, and assertions. Explain why this is the narrowest production-shaped test.>
|
||||||
|
|
||||||
|
## Hand-derived expected result
|
||||||
|
|
||||||
|
<Expected values or state derived independently of the implementation.>
|
||||||
|
|
||||||
|
## RED
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant failing output and why it failed for the expected missing behavior>
|
||||||
|
```
|
||||||
|
|
||||||
|
## GREEN
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant passing output>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected suite
|
||||||
|
|
||||||
|
**Command and result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact broader command and result>
|
||||||
|
```
|
||||||
|
|
||||||
|
## External-test boundaries
|
||||||
|
|
||||||
|
<What this test deliberately does not prove, including infrastructure or browser boundaries.>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Test Evidence: <short behavior name>
|
||||||
|
|
||||||
|
- **Test type:** Integration
|
||||||
|
- **Requirement IDs:** `<ID>`
|
||||||
|
- **Scenario IDs:** `<ID>`
|
||||||
|
- **Test class/method:** `<fully qualified class and method>`
|
||||||
|
- **Implementation commit:** `<short SHA or pending>`
|
||||||
|
|
||||||
|
## Protected behavior
|
||||||
|
|
||||||
|
<Externally observable rule and failure mode protected by this test.>
|
||||||
|
|
||||||
|
## Test method
|
||||||
|
|
||||||
|
<Setup, action, and assertions. Explain why this is the narrowest production-shaped test.>
|
||||||
|
|
||||||
|
## Hand-derived expected result
|
||||||
|
|
||||||
|
<Expected values or state derived independently of the implementation.>
|
||||||
|
|
||||||
|
## RED
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant failing output and why it failed for the expected missing behavior>
|
||||||
|
```
|
||||||
|
|
||||||
|
## GREEN
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant passing output>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected suite
|
||||||
|
|
||||||
|
**Command and result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact broader command and result>
|
||||||
|
```
|
||||||
|
|
||||||
|
## External-test boundaries
|
||||||
|
|
||||||
|
<What this test deliberately does not prove, including infrastructure or browser boundaries.>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Test Evidence: <short behavior name>
|
||||||
|
|
||||||
|
- **Test type:** Unit
|
||||||
|
- **Requirement IDs:** `<ID>`
|
||||||
|
- **Scenario IDs:** `<ID>`
|
||||||
|
- **Test class/method:** `<fully qualified class and method>`
|
||||||
|
- **Implementation commit:** `<short SHA or pending>`
|
||||||
|
|
||||||
|
## Protected behavior
|
||||||
|
|
||||||
|
<Externally observable rule and failure mode protected by this test.>
|
||||||
|
|
||||||
|
## Test method
|
||||||
|
|
||||||
|
<Setup, action, and assertions. Explain why this is the narrowest production-shaped test.>
|
||||||
|
|
||||||
|
## Hand-derived expected result
|
||||||
|
|
||||||
|
<Expected values or state derived independently of the implementation.>
|
||||||
|
|
||||||
|
## RED
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant failing output and why it failed for the expected missing behavior>
|
||||||
|
```
|
||||||
|
|
||||||
|
## GREEN
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant passing output>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected suite
|
||||||
|
|
||||||
|
**Command and result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact broader command and result>
|
||||||
|
```
|
||||||
|
|
||||||
|
## External-test boundaries
|
||||||
|
|
||||||
|
<What this test deliberately does not prove, including infrastructure or browser boundaries.>
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Test Evidence: <short behavior name>
|
||||||
|
|
||||||
|
- **Test type:** Web
|
||||||
|
- **Requirement IDs:** `<ID>`
|
||||||
|
- **Scenario IDs:** `<ID>`
|
||||||
|
- **Test class/method:** `<fully qualified class and method>`
|
||||||
|
- **Implementation commit:** `<short SHA or pending>`
|
||||||
|
|
||||||
|
## Protected behavior
|
||||||
|
|
||||||
|
<Externally observable rule and failure mode protected by this test.>
|
||||||
|
|
||||||
|
## Test method
|
||||||
|
|
||||||
|
<Setup, action, and assertions. Explain why this is the narrowest production-shaped test.>
|
||||||
|
|
||||||
|
## Hand-derived expected result
|
||||||
|
|
||||||
|
<Expected values or state derived independently of the implementation.>
|
||||||
|
|
||||||
|
## RED
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant failing output and why it failed for the expected missing behavior>
|
||||||
|
```
|
||||||
|
|
||||||
|
## GREEN
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact command>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<relevant passing output>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected suite
|
||||||
|
|
||||||
|
**Command and result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
<exact broader command and result>
|
||||||
|
```
|
||||||
|
|
||||||
|
## External-test boundaries
|
||||||
|
|
||||||
|
<What this test deliberately does not prove, including infrastructure or browser boundaries.>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: ${LAB_DB_URL:jdbc:postgresql://localhost:55432/labtimesheet}
|
||||||
|
username: ${LAB_DB_USERNAME:labtimesheet}
|
||||||
|
password: ${LAB_DB_PASSWORD:labtimesheet_dev}
|
||||||
|
mail:
|
||||||
|
host: ${LAB_SMTP_HOST:localhost}
|
||||||
|
port: ${LAB_SMTP_PORT:1025}
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: labtimesheet
|
name: labtimesheet
|
||||||
|
profiles:
|
||||||
|
default: dev
|
||||||
|
docker:
|
||||||
|
compose:
|
||||||
|
enabled: false
|
||||||
|
jpa:
|
||||||
|
open-in-view: false
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ package com.lab.labtimesheet;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
@Import(TestcontainersConfiguration.class)
|
@Import(TestcontainersConfiguration.class)
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
|
@ActiveProfiles("test")
|
||||||
class LabtimesheetApplicationTests {
|
class LabtimesheetApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class TestcontainersConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ServiceConnection
|
@ServiceConnection
|
||||||
PostgreSQLContainer postgresContainer() {
|
PostgreSQLContainer postgresContainer() {
|
||||||
return new PostgreSQLContainer(DockerImageName.parse("postgres:latest"));
|
return new PostgreSQLContainer(DockerImageName.parse("postgres:18.4"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
spring:
|
||||||
|
docker:
|
||||||
|
compose:
|
||||||
|
enabled: false
|
||||||
Reference in New Issue
Block a user