@aicgen/aicgen 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/.claude/agents/architecture-reviewer.md +88 -0
  2. package/.claude/agents/guideline-checker.md +73 -0
  3. package/.claude/agents/security-auditor.md +108 -0
  4. package/.claude/guidelines/api-design.md +645 -0
  5. package/.claude/guidelines/architecture.md +2503 -0
  6. package/.claude/guidelines/best-practices.md +618 -0
  7. package/.claude/guidelines/code-style.md +304 -0
  8. package/.claude/guidelines/design-patterns.md +573 -0
  9. package/.claude/guidelines/devops.md +226 -0
  10. package/.claude/guidelines/error-handling.md +413 -0
  11. package/.claude/guidelines/language.md +782 -0
  12. package/.claude/guidelines/performance.md +706 -0
  13. package/.claude/guidelines/security.md +583 -0
  14. package/.claude/guidelines/testing.md +568 -0
  15. package/.claude/settings.json +98 -0
  16. package/.claude/settings.local.json +8 -0
  17. package/.env.example +23 -0
  18. package/.eslintrc.json +28 -0
  19. package/.github/workflows/release.yml +180 -0
  20. package/.github/workflows/test.yml +81 -0
  21. package/.gitmodules +3 -0
  22. package/.vs/ProjectSettings.json +3 -0
  23. package/.vs/VSWorkspaceState.json +16 -0
  24. package/.vs/aicgen.slnx/FileContentIndex/5f0ce2a3-fd68-4863-9e23-e428cf1794e3.vsidx +0 -0
  25. package/.vs/aicgen.slnx/v18/.wsuo +0 -0
  26. package/.vs/aicgen.slnx/v18/DocumentLayout.json +54 -0
  27. package/.vs/slnx.sqlite +0 -0
  28. package/AGENTS.md +121 -0
  29. package/CLAUDE.md +36 -0
  30. package/CONTRIBUTING.md +821 -0
  31. package/LICENSE +21 -0
  32. package/README.md +199 -0
  33. package/assets/icon.svg +34 -0
  34. package/assets/logo.svg +41 -0
  35. package/bun.lock +848 -0
  36. package/data/LICENSE +21 -0
  37. package/data/README.md +203 -0
  38. package/data/api/basics.md +292 -0
  39. package/data/api/index.md +8 -0
  40. package/data/api/pagination.md +142 -0
  41. package/data/api/rest.md +137 -0
  42. package/data/api/versioning.md +60 -0
  43. package/data/architecture/clean-architecture/index.md +7 -0
  44. package/data/architecture/clean-architecture/layers.md +111 -0
  45. package/data/architecture/ddd/index.md +8 -0
  46. package/data/architecture/ddd/strategic.md +89 -0
  47. package/data/architecture/ddd/tactical.md +132 -0
  48. package/data/architecture/event-driven/index.md +7 -0
  49. package/data/architecture/event-driven/messaging.md +242 -0
  50. package/data/architecture/event-driven/patterns.md +129 -0
  51. package/data/architecture/feature-toggles/index.md +7 -0
  52. package/data/architecture/feature-toggles/patterns.md +73 -0
  53. package/data/architecture/gui/index.md +7 -0
  54. package/data/architecture/gui/patterns.md +132 -0
  55. package/data/architecture/hexagonal/ports-adapters.md +132 -0
  56. package/data/architecture/index.md +12 -0
  57. package/data/architecture/layered/index.md +7 -0
  58. package/data/architecture/layered/layers.md +100 -0
  59. package/data/architecture/microservices/api-gateway.md +56 -0
  60. package/data/architecture/microservices/boundaries.md +80 -0
  61. package/data/architecture/microservices/communication.md +97 -0
  62. package/data/architecture/microservices/data.md +92 -0
  63. package/data/architecture/microservices/index.md +11 -0
  64. package/data/architecture/microservices/resilience.md +111 -0
  65. package/data/architecture/modular-monolith/boundaries.md +133 -0
  66. package/data/architecture/modular-monolith/structure.md +131 -0
  67. package/data/architecture/serverless/best-practices.md +322 -0
  68. package/data/architecture/serverless/index.md +7 -0
  69. package/data/architecture/serverless/patterns.md +80 -0
  70. package/data/architecture/solid/index.md +7 -0
  71. package/data/architecture/solid/principles.md +187 -0
  72. package/data/database/basics.md +365 -0
  73. package/data/database/design-patterns.md +68 -0
  74. package/data/database/index.md +8 -0
  75. package/data/database/indexing.md +136 -0
  76. package/data/database/nosql.md +223 -0
  77. package/data/database/schema.md +137 -0
  78. package/data/devops/ci-cd.md +66 -0
  79. package/data/devops/index.md +8 -0
  80. package/data/devops/observability.md +73 -0
  81. package/data/devops/practices.md +77 -0
  82. package/data/error-handling/basics.md +222 -0
  83. package/data/error-handling/index.md +7 -0
  84. package/data/error-handling/strategy.md +185 -0
  85. package/data/guideline-mappings.yml +1077 -0
  86. package/data/index.md +3 -0
  87. package/data/language/csharp/basics.md +210 -0
  88. package/data/language/csharp/testing.md +252 -0
  89. package/data/language/go/basics.md +158 -0
  90. package/data/language/go/testing.md +192 -0
  91. package/data/language/index.md +14 -0
  92. package/data/language/java/basics.md +184 -0
  93. package/data/language/java/testing.md +273 -0
  94. package/data/language/javascript/basics.md +217 -0
  95. package/data/language/javascript/testing.md +269 -0
  96. package/data/language/python/async.md +100 -0
  97. package/data/language/python/basics.md +100 -0
  98. package/data/language/python/index.md +10 -0
  99. package/data/language/python/testing.md +125 -0
  100. package/data/language/python/types.md +99 -0
  101. package/data/language/ruby/basics.md +227 -0
  102. package/data/language/ruby/testing.md +267 -0
  103. package/data/language/rust/basics.md +175 -0
  104. package/data/language/rust/testing.md +219 -0
  105. package/data/language/typescript/async.md +103 -0
  106. package/data/language/typescript/basics.md +87 -0
  107. package/data/language/typescript/config.md +95 -0
  108. package/data/language/typescript/error-handling.md +98 -0
  109. package/data/language/typescript/generics.md +85 -0
  110. package/data/language/typescript/index.md +14 -0
  111. package/data/language/typescript/interfaces-types.md +83 -0
  112. package/data/language/typescript/performance.md +103 -0
  113. package/data/language/typescript/testing.md +98 -0
  114. package/data/patterns/base-patterns.md +105 -0
  115. package/data/patterns/concurrency.md +87 -0
  116. package/data/patterns/data-access.md +83 -0
  117. package/data/patterns/distribution.md +86 -0
  118. package/data/patterns/domain-logic.md +81 -0
  119. package/data/patterns/gof.md +109 -0
  120. package/data/patterns/index.md +12 -0
  121. package/data/performance/async.md +148 -0
  122. package/data/performance/basics.md +324 -0
  123. package/data/performance/caching-strategies.md +68 -0
  124. package/data/performance/caching.md +152 -0
  125. package/data/performance/index.md +8 -0
  126. package/data/practices/code-review.md +52 -0
  127. package/data/practices/documentation.md +260 -0
  128. package/data/practices/index.md +11 -0
  129. package/data/practices/planning.md +142 -0
  130. package/data/practices/refactoring.md +91 -0
  131. package/data/practices/version-control.md +55 -0
  132. package/data/security/auth-jwt.md +159 -0
  133. package/data/security/headers.md +143 -0
  134. package/data/security/index.md +10 -0
  135. package/data/security/injection.md +119 -0
  136. package/data/security/secrets.md +148 -0
  137. package/data/style/index.md +8 -0
  138. package/data/style/naming.md +136 -0
  139. package/data/style/organization.md +162 -0
  140. package/data/templates/agents/architecture-reviewer.md +88 -0
  141. package/data/templates/agents/guideline-checker.md +73 -0
  142. package/data/templates/agents/security-auditor.md +108 -0
  143. package/data/templates/antigravity/rules/architecture.md.hbs +5 -0
  144. package/data/templates/antigravity/rules/code-style.md.hbs +5 -0
  145. package/data/templates/antigravity/rules/language.md.hbs +5 -0
  146. package/data/templates/antigravity/rules/performance.md.hbs +5 -0
  147. package/data/templates/antigravity/rules/security.md.hbs +5 -0
  148. package/data/templates/antigravity/rules/testing.md.hbs +5 -0
  149. package/data/templates/antigravity/workflows/add-documentation.md.hbs +23 -0
  150. package/data/templates/antigravity/workflows/generate-integration-tests.md.hbs +17 -0
  151. package/data/templates/antigravity/workflows/generate-unit-tests.md.hbs +20 -0
  152. package/data/templates/antigravity/workflows/performance-audit.md.hbs +24 -0
  153. package/data/templates/antigravity/workflows/refactor-extract-module.md.hbs +17 -0
  154. package/data/templates/antigravity/workflows/security-audit.md.hbs +20 -0
  155. package/data/templates/hooks/formatting.json +26 -0
  156. package/data/templates/hooks/security.json +35 -0
  157. package/data/templates/hooks/testing.json +17 -0
  158. package/data/testing/basics.md +151 -0
  159. package/data/testing/index.md +9 -0
  160. package/data/testing/integration.md +159 -0
  161. package/data/testing/unit-fundamentals.md +128 -0
  162. package/data/testing/unit-mocking.md +116 -0
  163. package/data/version.json +49 -0
  164. package/dist/commands/init.d.ts +8 -0
  165. package/dist/commands/init.d.ts.map +1 -0
  166. package/dist/commands/init.js +46 -0
  167. package/dist/commands/init.js.map +1 -0
  168. package/dist/config/profiles.d.ts +4 -0
  169. package/dist/config/profiles.d.ts.map +1 -0
  170. package/dist/config/profiles.js +30 -0
  171. package/dist/config/profiles.js.map +1 -0
  172. package/dist/config/settings.d.ts +7 -0
  173. package/dist/config/settings.d.ts.map +1 -0
  174. package/dist/config/settings.js +7 -0
  175. package/dist/config/settings.js.map +1 -0
  176. package/dist/index.d.ts +3 -0
  177. package/dist/index.d.ts.map +1 -0
  178. package/dist/index.js +58489 -0
  179. package/dist/index.js.map +1 -0
  180. package/dist/models/guideline.d.ts +15 -0
  181. package/dist/models/guideline.d.ts.map +1 -0
  182. package/dist/models/guideline.js +2 -0
  183. package/dist/models/guideline.js.map +1 -0
  184. package/dist/models/preference.d.ts +9 -0
  185. package/dist/models/preference.d.ts.map +1 -0
  186. package/dist/models/preference.js +2 -0
  187. package/dist/models/preference.js.map +1 -0
  188. package/dist/models/profile.d.ts +9 -0
  189. package/dist/models/profile.d.ts.map +1 -0
  190. package/dist/models/profile.js +2 -0
  191. package/dist/models/profile.js.map +1 -0
  192. package/dist/models/project.d.ts +13 -0
  193. package/dist/models/project.d.ts.map +1 -0
  194. package/dist/models/project.js +2 -0
  195. package/dist/models/project.js.map +1 -0
  196. package/dist/services/ai/anthropic.d.ts +7 -0
  197. package/dist/services/ai/anthropic.d.ts.map +1 -0
  198. package/dist/services/ai/anthropic.js +39 -0
  199. package/dist/services/ai/anthropic.js.map +1 -0
  200. package/dist/services/generator.d.ts +2 -0
  201. package/dist/services/generator.d.ts.map +1 -0
  202. package/dist/services/generator.js +4 -0
  203. package/dist/services/generator.js.map +1 -0
  204. package/dist/services/learner.d.ts +2 -0
  205. package/dist/services/learner.d.ts.map +1 -0
  206. package/dist/services/learner.js +4 -0
  207. package/dist/services/learner.js.map +1 -0
  208. package/dist/services/scanner.d.ts +3 -0
  209. package/dist/services/scanner.d.ts.map +1 -0
  210. package/dist/services/scanner.js +54 -0
  211. package/dist/services/scanner.js.map +1 -0
  212. package/dist/utils/errors.d.ts +15 -0
  213. package/dist/utils/errors.d.ts.map +1 -0
  214. package/dist/utils/errors.js +27 -0
  215. package/dist/utils/errors.js.map +1 -0
  216. package/dist/utils/file.d.ts +7 -0
  217. package/dist/utils/file.d.ts.map +1 -0
  218. package/dist/utils/file.js +32 -0
  219. package/dist/utils/file.js.map +1 -0
  220. package/dist/utils/logger.d.ts +6 -0
  221. package/dist/utils/logger.d.ts.map +1 -0
  222. package/dist/utils/logger.js +17 -0
  223. package/dist/utils/logger.js.map +1 -0
  224. package/dist/utils/path.d.ts +6 -0
  225. package/dist/utils/path.d.ts.map +1 -0
  226. package/dist/utils/path.js +14 -0
  227. package/dist/utils/path.js.map +1 -0
  228. package/docs/planning/memory-lane.md +83 -0
  229. package/package.json +64 -0
  230. package/packaging/linux/aicgen.spec +23 -0
  231. package/packaging/linux/control +9 -0
  232. package/packaging/macos/scripts/postinstall +12 -0
  233. package/packaging/windows/setup.nsi +92 -0
  234. package/planning/BRANDING-SUMMARY.md +194 -0
  235. package/planning/BRANDING.md +174 -0
  236. package/planning/BUILD.md +186 -0
  237. package/planning/CHUNK-IMPLEMENTATION-PLAN.md +87 -0
  238. package/planning/CHUNK-TAXONOMY.md +375 -0
  239. package/planning/CHUNKS-COMPLETE.md +382 -0
  240. package/planning/DESIGN.md +313 -0
  241. package/planning/DYNAMIC-GUIDELINES-DESIGN.md +265 -0
  242. package/planning/ENTERPRISE-UX-COMPLETE.md +281 -0
  243. package/planning/IMPLEMENTATION-PLAN.md +20 -0
  244. package/planning/PHASE1-COMPLETE.md +211 -0
  245. package/planning/PHASE2-COMPLETE.md +350 -0
  246. package/planning/PHASE3-COMPLETE.md +399 -0
  247. package/planning/PHASE4-COMPLETE.md +361 -0
  248. package/planning/PHASE4.5-CHUNKS.md +462 -0
  249. package/planning/STRUCTURE.md +170 -0
  250. package/scripts/add-categories.ts +87 -0
  251. package/scripts/build-binary.ts +46 -0
  252. package/scripts/embed-data.ts +105 -0
  253. package/scripts/generate-version.ts +150 -0
  254. package/scripts/test-decompress.ts +27 -0
  255. package/scripts/test-extract.ts +31 -0
  256. package/src/__tests__/services/assistant-file-writer.test.ts +400 -0
  257. package/src/__tests__/services/guideline-loader.test.ts +281 -0
  258. package/src/__tests__/services/tarball-extraction.test.ts +125 -0
  259. package/src/commands/add-guideline.ts +296 -0
  260. package/src/commands/clear.ts +61 -0
  261. package/src/commands/guideline-selector.ts +123 -0
  262. package/src/commands/init.ts +645 -0
  263. package/src/commands/quick-add.ts +586 -0
  264. package/src/commands/remove-guideline.ts +152 -0
  265. package/src/commands/stats.ts +49 -0
  266. package/src/commands/update.ts +240 -0
  267. package/src/config.ts +82 -0
  268. package/src/embedded-data.ts +1492 -0
  269. package/src/index.ts +67 -0
  270. package/src/models/profile.ts +24 -0
  271. package/src/models/project.ts +43 -0
  272. package/src/services/assistant-file-writer.ts +612 -0
  273. package/src/services/config-generator.ts +150 -0
  274. package/src/services/config-manager.ts +70 -0
  275. package/src/services/data-source.ts +248 -0
  276. package/src/services/first-run-init.ts +148 -0
  277. package/src/services/guideline-loader.ts +311 -0
  278. package/src/services/hook-generator.ts +178 -0
  279. package/src/services/subagent-generator.ts +310 -0
  280. package/src/utils/banner.ts +66 -0
  281. package/src/utils/errors.ts +27 -0
  282. package/src/utils/file.ts +67 -0
  283. package/src/utils/formatting.ts +172 -0
  284. package/src/utils/logger.ts +89 -0
  285. package/src/utils/path.ts +17 -0
  286. package/src/utils/wizard-state.ts +132 -0
  287. package/tsconfig.json +25 -0
@@ -0,0 +1,192 @@
1
+ # Go Testing
2
+
3
+ ## Test File Structure
4
+
5
+ ```
6
+ myproject/
7
+ ├── user.go
8
+ ├── user_test.go # Tests alongside source
9
+ ├── user_internal_test.go # Internal tests (same package)
10
+ └── testdata/ # Test fixtures
11
+ └── fixtures.json
12
+ ```
13
+
14
+ ## Test Functions
15
+
16
+ ```go
17
+ // Basic test
18
+ func TestCreateUser(t *testing.T) {
19
+ user := CreateUser("test@example.com")
20
+
21
+ if user.Email != "test@example.com" {
22
+ t.Errorf("expected email %q, got %q", "test@example.com", user.Email)
23
+ }
24
+ }
25
+
26
+ // Table-driven tests (preferred)
27
+ func TestValidateEmail(t *testing.T) {
28
+ tests := []struct {
29
+ name string
30
+ email string
31
+ wantErr bool
32
+ }{
33
+ {"valid email", "test@example.com", false},
34
+ {"missing @", "invalid", true},
35
+ {"empty", "", true},
36
+ }
37
+
38
+ for _, tt := range tests {
39
+ t.Run(tt.name, func(t *testing.T) {
40
+ err := ValidateEmail(tt.email)
41
+ if (err != nil) != tt.wantErr {
42
+ t.Errorf("ValidateEmail(%q) error = %v, wantErr %v",
43
+ tt.email, err, tt.wantErr)
44
+ }
45
+ })
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## Subtests and Parallel
51
+
52
+ ```go
53
+ func TestUserService(t *testing.T) {
54
+ t.Run("Create", func(t *testing.T) {
55
+ t.Parallel() // Run in parallel
56
+ // test create
57
+ })
58
+
59
+ t.Run("Update", func(t *testing.T) {
60
+ t.Parallel()
61
+ // test update
62
+ })
63
+ }
64
+ ```
65
+
66
+ ## Test Helpers
67
+
68
+ ```go
69
+ // Helper function (call t.Helper() first)
70
+ func createTestUser(t *testing.T, email string) *User {
71
+ t.Helper()
72
+ user, err := NewUser(email)
73
+ if err != nil {
74
+ t.Fatalf("failed to create test user: %v", err)
75
+ }
76
+ return user
77
+ }
78
+
79
+ // Cleanup
80
+ func TestWithTempFile(t *testing.T) {
81
+ f, err := os.CreateTemp("", "test")
82
+ if err != nil {
83
+ t.Fatal(err)
84
+ }
85
+ t.Cleanup(func() { os.Remove(f.Name()) })
86
+
87
+ // use f...
88
+ }
89
+ ```
90
+
91
+ ## Mocking with Interfaces
92
+
93
+ ```go
94
+ // Define interface for dependency
95
+ type UserRepository interface {
96
+ Save(user *User) error
97
+ FindByID(id string) (*User, error)
98
+ }
99
+
100
+ // Mock implementation
101
+ type mockRepository struct {
102
+ users map[string]*User
103
+ saveErr error
104
+ }
105
+
106
+ func (m *mockRepository) Save(user *User) error {
107
+ if m.saveErr != nil {
108
+ return m.saveErr
109
+ }
110
+ m.users[user.ID] = user
111
+ return nil
112
+ }
113
+
114
+ func (m *mockRepository) FindByID(id string) (*User, error) {
115
+ if user, ok := m.users[id]; ok {
116
+ return user, nil
117
+ }
118
+ return nil, ErrNotFound
119
+ }
120
+
121
+ // Use in tests
122
+ func TestUserService_Create(t *testing.T) {
123
+ repo := &mockRepository{users: make(map[string]*User)}
124
+ service := NewUserService(repo)
125
+
126
+ user, err := service.Create("test@example.com")
127
+
128
+ if err != nil {
129
+ t.Fatalf("unexpected error: %v", err)
130
+ }
131
+ if _, exists := repo.users[user.ID]; !exists {
132
+ t.Error("user not saved to repository")
133
+ }
134
+ }
135
+ ```
136
+
137
+ ## Benchmarks
138
+
139
+ ```go
140
+ func BenchmarkProcessUsers(b *testing.B) {
141
+ users := generateTestUsers(1000)
142
+ b.ResetTimer()
143
+
144
+ for i := 0; i < b.N; i++ {
145
+ ProcessUsers(users)
146
+ }
147
+ }
148
+
149
+ // Run: go test -bench=. -benchmem
150
+ ```
151
+
152
+ ## Test Coverage
153
+
154
+ ```bash
155
+ # Generate coverage
156
+ go test -coverprofile=coverage.out ./...
157
+
158
+ # View coverage report
159
+ go tool cover -html=coverage.out
160
+
161
+ # Check coverage percentage
162
+ go test -cover ./...
163
+ ```
164
+
165
+ ## Integration Tests
166
+
167
+ ```go
168
+ //go:build integration
169
+
170
+ package mypackage_test
171
+
172
+ import (
173
+ "testing"
174
+ "database/sql"
175
+ )
176
+
177
+ func TestDatabaseIntegration(t *testing.T) {
178
+ if testing.Short() {
179
+ t.Skip("skipping integration test")
180
+ }
181
+
182
+ db, err := sql.Open("postgres", os.Getenv("TEST_DATABASE_URL"))
183
+ if err != nil {
184
+ t.Fatal(err)
185
+ }
186
+ t.Cleanup(func() { db.Close() })
187
+
188
+ // integration tests...
189
+ }
190
+
191
+ // Run: go test -tags=integration ./...
192
+ ```
@@ -0,0 +1,14 @@
1
+ # Language-Specific Guidelines
2
+
3
+ Programming language best practices and idioms.
4
+
5
+ ## Available Languages
6
+
7
+ - `typescript/` - TypeScript guidelines
8
+ - `javascript/` - JavaScript (ES6+) guidelines
9
+ - `python/` - Python guidelines
10
+ - `go/` - Go guidelines
11
+ - `rust/` - Rust guidelines
12
+ - `java/` - Java guidelines
13
+ - `csharp/` - C# guidelines
14
+ - `ruby/` - Ruby guidelines
@@ -0,0 +1,184 @@
1
+ # Java Fundamentals
2
+
3
+ ## Project Structure (Maven/Gradle)
4
+
5
+ ```
6
+ myproject/
7
+ ├── src/
8
+ │ ├── main/
9
+ │ │ ├── java/
10
+ │ │ │ └── com/example/
11
+ │ │ │ ├── Application.java
12
+ │ │ │ ├── controller/
13
+ │ │ │ ├── service/
14
+ │ │ │ ├── repository/
15
+ │ │ │ └── model/
16
+ │ │ └── resources/
17
+ │ │ └── application.yml
18
+ │ └── test/
19
+ │ └── java/
20
+ ├── pom.xml (Maven) or build.gradle (Gradle)
21
+ ```
22
+
23
+ ## Naming Conventions
24
+
25
+ ```java
26
+ // Classes: PascalCase
27
+ public class UserService {}
28
+
29
+ // Interfaces: PascalCase, often -able suffix
30
+ public interface Comparable {}
31
+ public interface UserRepository {}
32
+
33
+ // Methods/variables: camelCase
34
+ public void createUser() {}
35
+ private String userName;
36
+
37
+ // Constants: UPPER_SNAKE_CASE
38
+ public static final int MAX_RETRIES = 3;
39
+
40
+ // Packages: lowercase
41
+ package com.example.service;
42
+ ```
43
+
44
+ ## Modern Java Features (17+)
45
+
46
+ ```java
47
+ // Records for immutable data
48
+ public record User(String id, String email, String name) {}
49
+
50
+ // Pattern matching
51
+ if (obj instanceof String s) {
52
+ System.out.println(s.length());
53
+ }
54
+
55
+ // Switch expressions
56
+ String result = switch (status) {
57
+ case ACTIVE -> "Active";
58
+ case PENDING -> "Pending";
59
+ case DELETED -> "Deleted";
60
+ };
61
+
62
+ // Text blocks
63
+ String json = """
64
+ {
65
+ "name": "test",
66
+ "value": 123
67
+ }
68
+ """;
69
+
70
+ // Sealed classes
71
+ public sealed interface Shape permits Circle, Rectangle {}
72
+ ```
73
+
74
+ ## Exception Handling
75
+
76
+ ```java
77
+ // Checked exceptions
78
+ public User findUser(String id) throws UserNotFoundException {
79
+ return repository.findById(id)
80
+ .orElseThrow(() -> new UserNotFoundException(id));
81
+ }
82
+
83
+ // Try-with-resources
84
+ try (var reader = new BufferedReader(new FileReader(path))) {
85
+ return reader.readLine();
86
+ } catch (IOException e) {
87
+ throw new DataAccessException("Failed to read file", e);
88
+ }
89
+
90
+ // Custom exceptions
91
+ public class UserNotFoundException extends RuntimeException {
92
+ public UserNotFoundException(String id) {
93
+ super("User not found: " + id);
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Optional
99
+
100
+ ```java
101
+ // Avoid null, use Optional
102
+ public Optional<User> findUser(String id) {
103
+ return Optional.ofNullable(repository.find(id));
104
+ }
105
+
106
+ // Chaining
107
+ findUser(id)
108
+ .map(User::getEmail)
109
+ .filter(email -> email.contains("@"))
110
+ .orElse("unknown@example.com");
111
+
112
+ // Never use Optional in fields or parameters
113
+ // Only for return types
114
+ ```
115
+
116
+ ## Streams
117
+
118
+ ```java
119
+ // Filter, map, collect
120
+ List<String> emails = users.stream()
121
+ .filter(u -> u.isActive())
122
+ .map(User::getEmail)
123
+ .collect(Collectors.toList());
124
+
125
+ // Grouping
126
+ Map<String, List<User>> byDepartment = users.stream()
127
+ .collect(Collectors.groupingBy(User::getDepartment));
128
+
129
+ // Reduce
130
+ int totalAge = users.stream()
131
+ .mapToInt(User::getAge)
132
+ .sum();
133
+ ```
134
+
135
+ ## Testing (JUnit 5)
136
+
137
+ ```java
138
+ @ExtendWith(MockitoExtension.class)
139
+ class UserServiceTest {
140
+
141
+ @Mock
142
+ private UserRepository repository;
143
+
144
+ @InjectMocks
145
+ private UserService service;
146
+
147
+ @Test
148
+ void shouldCreateUser() {
149
+ // Arrange
150
+ var request = new CreateUserRequest("test@example.com");
151
+ when(repository.save(any())).thenReturn(new User("1", "test@example.com"));
152
+
153
+ // Act
154
+ var user = service.create(request);
155
+
156
+ // Assert
157
+ assertThat(user.getEmail()).isEqualTo("test@example.com");
158
+ verify(repository).save(any());
159
+ }
160
+
161
+ @ParameterizedTest
162
+ @ValueSource(strings = {"invalid", "no-at", ""})
163
+ void shouldRejectInvalidEmails(String email) {
164
+ assertThrows(ValidationException.class,
165
+ () -> service.create(new CreateUserRequest(email)));
166
+ }
167
+ }
168
+ ```
169
+
170
+ ## Dependency Injection (Spring)
171
+
172
+ ```java
173
+ @Service
174
+ public class UserService {
175
+ private final UserRepository repository;
176
+ private final EmailService emailService;
177
+
178
+ // Constructor injection (preferred)
179
+ public UserService(UserRepository repository, EmailService emailService) {
180
+ this.repository = repository;
181
+ this.emailService = emailService;
182
+ }
183
+ }
184
+ ```
@@ -0,0 +1,273 @@
1
+ # Java Testing (JUnit 5)
2
+
3
+ ## Test Structure
4
+
5
+ ```
6
+ src/
7
+ ├── main/java/com/example/
8
+ │ └── UserService.java
9
+ └── test/java/com/example/
10
+ └── UserServiceTest.java
11
+ ```
12
+
13
+ ## Basic Tests
14
+
15
+ ```java
16
+ import org.junit.jupiter.api.*;
17
+ import static org.junit.jupiter.api.Assertions.*;
18
+
19
+ class UserServiceTest {
20
+
21
+ private UserService service;
22
+
23
+ @BeforeEach
24
+ void setUp() {
25
+ service = new UserService();
26
+ }
27
+
28
+ @Test
29
+ void createUser_WithValidEmail_ReturnsUser() {
30
+ User user = service.create("test@example.com");
31
+
32
+ assertEquals("test@example.com", user.getEmail());
33
+ assertNotNull(user.getId());
34
+ }
35
+
36
+ @Test
37
+ void createUser_WithInvalidEmail_ThrowsException() {
38
+ assertThrows(ValidationException.class, () -> {
39
+ service.create("invalid");
40
+ });
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Assertions
46
+
47
+ ```java
48
+ // Equality
49
+ assertEquals(expected, actual);
50
+ assertNotEquals(unexpected, actual);
51
+
52
+ // Boolean
53
+ assertTrue(condition);
54
+ assertFalse(condition);
55
+
56
+ // Null checks
57
+ assertNull(value);
58
+ assertNotNull(value);
59
+
60
+ // Collections
61
+ assertIterableEquals(expected, actual);
62
+ assertArrayEquals(expectedArray, actualArray);
63
+
64
+ // Multiple assertions (all run even if some fail)
65
+ assertAll(
66
+ () -> assertEquals("John", user.getName()),
67
+ () -> assertEquals("john@example.com", user.getEmail()),
68
+ () -> assertTrue(user.isActive())
69
+ );
70
+ ```
71
+
72
+ ## Parameterized Tests
73
+
74
+ ```java
75
+ @ParameterizedTest
76
+ @ValueSource(strings = {"", " ", "invalid", "no-at-sign"})
77
+ void validateEmail_WithInvalidInput_ReturnsFalse(String email) {
78
+ assertFalse(validator.isValid(email));
79
+ }
80
+
81
+ @ParameterizedTest
82
+ @CsvSource({
83
+ "test@example.com, true",
84
+ "invalid, false",
85
+ "'', false"
86
+ })
87
+ void validateEmail_WithVariousInputs(String email, boolean expected) {
88
+ assertEquals(expected, validator.isValid(email));
89
+ }
90
+
91
+ @ParameterizedTest
92
+ @MethodSource("provideUsersForTest")
93
+ void processUser_WithVariousUsers(User user, String expectedStatus) {
94
+ assertEquals(expectedStatus, processor.process(user));
95
+ }
96
+
97
+ static Stream<Arguments> provideUsersForTest() {
98
+ return Stream.of(
99
+ Arguments.of(new User("active@example.com", true), "processed"),
100
+ Arguments.of(new User("inactive@example.com", false), "skipped")
101
+ );
102
+ }
103
+ ```
104
+
105
+ ## Nested Tests
106
+
107
+ ```java
108
+ @DisplayName("UserService")
109
+ class UserServiceTest {
110
+
111
+ @Nested
112
+ @DisplayName("create")
113
+ class Create {
114
+
115
+ @Test
116
+ @DisplayName("with valid email creates user")
117
+ void withValidEmail() {
118
+ // test
119
+ }
120
+
121
+ @Test
122
+ @DisplayName("with duplicate email throws exception")
123
+ void withDuplicateEmail() {
124
+ // test
125
+ }
126
+ }
127
+
128
+ @Nested
129
+ @DisplayName("delete")
130
+ class Delete {
131
+ // delete tests
132
+ }
133
+ }
134
+ ```
135
+
136
+ ## Mocking with Mockito
137
+
138
+ ```java
139
+ import org.mockito.*;
140
+ import static org.mockito.Mockito.*;
141
+
142
+ @ExtendWith(MockitoExtension.class)
143
+ class UserServiceTest {
144
+
145
+ @Mock
146
+ private UserRepository repository;
147
+
148
+ @InjectMocks
149
+ private UserService service;
150
+
151
+ @Test
152
+ void create_SavesUserToRepository() {
153
+ User user = new User("test@example.com");
154
+ when(repository.save(any(User.class))).thenReturn(user);
155
+
156
+ User result = service.create("test@example.com");
157
+
158
+ verify(repository).save(any(User.class));
159
+ assertEquals("test@example.com", result.getEmail());
160
+ }
161
+
162
+ @Test
163
+ void findById_WhenNotFound_ThrowsException() {
164
+ when(repository.findById("123")).thenReturn(Optional.empty());
165
+
166
+ assertThrows(NotFoundException.class, () -> {
167
+ service.findById("123");
168
+ });
169
+ }
170
+ }
171
+ ```
172
+
173
+ ## Lifecycle Hooks
174
+
175
+ ```java
176
+ @BeforeAll
177
+ static void initAll() {
178
+ // Run once before all tests
179
+ }
180
+
181
+ @BeforeEach
182
+ void init() {
183
+ // Run before each test
184
+ }
185
+
186
+ @AfterEach
187
+ void tearDown() {
188
+ // Run after each test
189
+ }
190
+
191
+ @AfterAll
192
+ static void tearDownAll() {
193
+ // Run once after all tests
194
+ }
195
+ ```
196
+
197
+ ## Async Testing
198
+
199
+ ```java
200
+ @Test
201
+ void asyncOperation_CompletesWithinTimeout() {
202
+ assertTimeout(Duration.ofSeconds(2), () -> {
203
+ service.longRunningOperation();
204
+ });
205
+ }
206
+
207
+ @Test
208
+ void asyncOperation_WithCompletableFuture() throws Exception {
209
+ CompletableFuture<User> future = service.createAsync("test@example.com");
210
+
211
+ User user = future.get(5, TimeUnit.SECONDS);
212
+ assertEquals("test@example.com", user.getEmail());
213
+ }
214
+ ```
215
+
216
+ ## Test Tags and Filtering
217
+
218
+ ```java
219
+ @Tag("integration")
220
+ @Test
221
+ void databaseIntegrationTest() {
222
+ // integration test
223
+ }
224
+
225
+ @Tag("slow")
226
+ @Test
227
+ void slowPerformanceTest() {
228
+ // slow test
229
+ }
230
+
231
+ // Run: mvn test -Dgroups="integration"
232
+ // Exclude: mvn test -DexcludedGroups="slow"
233
+ ```
234
+
235
+ ## Spring Boot Testing
236
+
237
+ ```java
238
+ @SpringBootTest
239
+ class UserServiceIntegrationTest {
240
+
241
+ @Autowired
242
+ private UserService service;
243
+
244
+ @MockBean
245
+ private EmailService emailService;
246
+
247
+ @Test
248
+ void create_SendsWelcomeEmail() {
249
+ service.create("test@example.com");
250
+
251
+ verify(emailService).sendWelcome(any(User.class));
252
+ }
253
+ }
254
+
255
+ @WebMvcTest(UserController.class)
256
+ class UserControllerTest {
257
+
258
+ @Autowired
259
+ private MockMvc mockMvc;
260
+
261
+ @MockBean
262
+ private UserService service;
263
+
264
+ @Test
265
+ void getUser_ReturnsUser() throws Exception {
266
+ when(service.findById("1")).thenReturn(new User("1", "test@example.com"));
267
+
268
+ mockMvc.perform(get("/users/1"))
269
+ .andExpect(status().isOk())
270
+ .andExpect(jsonPath("$.email").value("test@example.com"));
271
+ }
272
+ }
273
+ ```