Last active
February 11, 2026 19:03
-
-
Save musketyr/61d09ebbf516b956efdd722b6e2ad8e9 to your computer and use it in GitHub Desktop.
Spock → JUnit 5 Migration: NumberUtilsSpec (sc185871)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Spock → JUnit 5 Migration: NumberUtilsSpec</title> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; padding: 20px; line-height: 1.6; } | |
| h1 { text-align: center; margin-bottom: 20px; color: #333; } | |
| .section { background: white; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); overflow: hidden; } | |
| .section-header { background: #2d3748; color: white; padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; } | |
| .section-header:hover { background: #4a5568; } | |
| .section-header h2 { font-size: 16px; font-weight: 600; } | |
| .section-header .toggle { font-size: 12px; } | |
| .section-content { display: block; } | |
| .section-content.collapsed { display: none; } | |
| .diff-container { display: grid; grid-template-columns: 1fr 1fr; } | |
| .diff-panel { padding: 16px; overflow-x: auto; } | |
| .diff-panel.left { background: #fff5f5; border-right: 1px solid #e2e8f0; } | |
| .diff-panel.right { background: #f0fff4; } | |
| .diff-panel h3 { font-size: 12px; text-transform: uppercase; color: #718096; margin-bottom: 12px; letter-spacing: 0.5px; } | |
| pre { font-family: 'SF Mono', Monaco, 'Courier New', monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word; } | |
| .left pre { color: #c53030; } | |
| .right pre { color: #276749; } | |
| .summary { background: #c6f6d5; border-left: 4px solid #38a169; padding: 12px 16px; margin: 0; } | |
| .summary p { color: #276749; font-size: 14px; } | |
| .summary strong { color: #22543d; } | |
| @media (max-width: 768px) { .diff-container { grid-template-columns: 1fr; } .diff-panel.left { border-right: none; border-bottom: 1px solid #e2e8f0; } } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>🦀 Spock → JUnit 5 Migration: NumberUtilsSpec</h1> | |
| <p style="text-align: center; color: #666; margin-bottom: 20px;">Story: <a href="https://app.shortcut.com/agorapulse/story/185871">sc185871</a> | PR: <a href="https://github.com/agorapulse/platform/pull/72701">#72701</a></p> | |
| <!-- Section: Imports --> | |
| <div class="section"> | |
| <div class="section-header" onclick="toggleSection(this)"> | |
| <h2>📦 Imports</h2> | |
| <span class="toggle">▼</span> | |
| </div> | |
| <div class="section-content"> | |
| <div class="diff-container"> | |
| <div class="diff-panel left"> | |
| <h3>Spock (Groovy)</h3> | |
| <pre>package agorapulse.roi.core.utils | |
| import spock.lang.Specification</pre> | |
| </div> | |
| <div class="diff-panel right"> | |
| <h3>JUnit 5 (Java)</h3> | |
| <pre>package agorapulse.roi.core.utils; | |
| import org.junit.jupiter.api.Test; | |
| import java.math.BigDecimal; | |
| import java.util.List; | |
| import static org.assertj.core.api.Assertions.assertThat;</pre> | |
| </div> | |
| </div> | |
| <div class="summary"> | |
| <p><strong>Changes:</strong> Replaced Spock Specification import with JUnit 5 @Test, AssertJ assertions, and explicit Java imports for BigDecimal and List.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section: Class & Fields --> | |
| <div class="section"> | |
| <div class="section-header" onclick="toggleSection(this)"> | |
| <h2>🏗️ Class & Fields</h2> | |
| <span class="toggle">▼</span> | |
| </div> | |
| <div class="section-content"> | |
| <div class="diff-container"> | |
| <div class="diff-panel left"> | |
| <h3>Spock (Groovy)</h3> | |
| <pre>class NumberUtilsSpec extends Specification {</pre> | |
| </div> | |
| <div class="diff-panel right"> | |
| <h3>JUnit 5 (Java)</h3> | |
| <pre>class NumberUtilsTest {</pre> | |
| </div> | |
| </div> | |
| <div class="summary"> | |
| <p><strong>Changes:</strong> Removed Specification inheritance (no mocks needed for this utility test), renamed Spec → Test.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Section: Tests --> | |
| <div class="section"> | |
| <div class="section-header" onclick="toggleSection(this)"> | |
| <h2>🧪 Tests</h2> | |
| <span class="toggle">▼</span> | |
| </div> | |
| <div class="section-content"> | |
| <div class="diff-container"> | |
| <div class="diff-panel left"> | |
| <h3>Spock (Groovy)</h3> | |
| <pre>void "addNotNull should add value when valueToAdd is not null"() { | |
| when: | |
| BigDecimal originalValue = BigDecimal.valueOf(10) | |
| BigDecimal result = NumberUtils.addNotNull(originalValue, BigDecimal.valueOf(5)) | |
| then: | |
| result == BigDecimal.valueOf(15) | |
| } | |
| void "addNotNull should return originalValue when valueToAdd is null"() { | |
| when: | |
| BigDecimal originalValue = BigDecimal.valueOf(10) | |
| BigDecimal result = NumberUtils.addNotNull(originalValue, null) | |
| then: | |
| result == originalValue | |
| } | |
| void "isNotNullOrNotZero should return true for non-null and non-zero BigDecimal"() { | |
| expect: | |
| NumberUtils.isNotNullOrNotZero(BigDecimal.valueOf(5)) | |
| } | |
| void "isNotNullOrNotZero should return false for null BigDecimal"() { | |
| expect: | |
| !NumberUtils.isNotNullOrNotZero(null as BigDecimal) | |
| } | |
| void "isNotNullOrNotZero should return false for zero BigDecimal"() { | |
| expect: | |
| !NumberUtils.isNotNullOrNotZero(BigDecimal.ZERO) | |
| } | |
| void 'should calculateRatio'() { | |
| when: | |
| BigDecimal result = NumberUtils.calculateRatio(5, 200000) | |
| then: | |
| result == BigDecimal.valueOf(0.003) | |
| } | |
| void 'should calculateRatio - divide by 0'() { | |
| when: | |
| BigDecimal result = NumberUtils.calculateRatio(5, 0) | |
| then: | |
| result == BigDecimal.ZERO | |
| } | |
| void "should calculate standard deviation from a list of values"() { | |
| given: | |
| List<BigDecimal> givenValues = [2.0g, 7.0g, 3.0g, 12.0g, 9.0g,] | |
| when: | |
| BigDecimal actualStandardDeviation = NumberUtils.getStandardDeviation(givenValues) | |
| then: | |
| BigDecimal expectedStandardDeviation = 3.72g.setScale(2, NumberUtils.ROUNDING_MODE) | |
| actualStandardDeviation == expectedStandardDeviation | |
| } | |
| void "should calculate median from a list of odd number of values"() { | |
| given: | |
| List<BigDecimal> givenValues = [24.1g, 25.0g, 25.2g, 25.6g, 25.7g, 26.1g, 27.8g,] | |
| when: | |
| BigDecimal actualMedian = NumberUtils.getMedian(givenValues) | |
| then: | |
| BigDecimal expectedMedian = 25.6g.setScale(2, NumberUtils.ROUNDING_MODE) | |
| actualMedian == expectedMedian | |
| } | |
| void "should calculate median from a list of even number of values"() { | |
| given: | |
| List<BigDecimal> givenValues = [24.1g, 24.7g, 25.0g, 25.2g, 25.6g, 25.7g, 26.1g, 27.8g,] | |
| when: | |
| BigDecimal actualMedian = NumberUtils.getMedian(givenValues) | |
| then: | |
| BigDecimal expectedMedian = 25.40g.setScale(2, NumberUtils.ROUNDING_MODE) | |
| actualMedian == expectedMedian | |
| }</pre> | |
| </div> | |
| <div class="diff-panel right"> | |
| <h3>JUnit 5 (Java)</h3> | |
| <pre>@Test | |
| void addNotNull_should_add_value_when_valueToAdd_is_not_null() { | |
| // when | |
| BigDecimal originalValue = BigDecimal.valueOf(10); | |
| BigDecimal result = NumberUtils.addNotNull(originalValue, BigDecimal.valueOf(5)); | |
| // then | |
| assertThat(result).isEqualTo(BigDecimal.valueOf(15)); | |
| } | |
| @Test | |
| void addNotNull_should_return_originalValue_when_valueToAdd_is_null() { | |
| // when | |
| BigDecimal originalValue = BigDecimal.valueOf(10); | |
| BigDecimal result = NumberUtils.addNotNull(originalValue, null); | |
| // then | |
| assertThat(result).isEqualTo(originalValue); | |
| } | |
| @Test | |
| void isNotNullOrNotZero_should_return_true_for_non_null_and_non_zero_BigDecimal() { | |
| assertThat(NumberUtils.isNotNullOrNotZero(BigDecimal.valueOf(5))).isTrue(); | |
| } | |
| @Test | |
| void isNotNullOrNotZero_should_return_false_for_null_BigDecimal() { | |
| assertThat(NumberUtils.isNotNullOrNotZero((BigDecimal) null)).isFalse(); | |
| } | |
| @Test | |
| void isNotNullOrNotZero_should_return_false_for_zero_BigDecimal() { | |
| assertThat(NumberUtils.isNotNullOrNotZero(BigDecimal.ZERO)).isFalse(); | |
| } | |
| @Test | |
| void should_calculateRatio() { | |
| // when | |
| BigDecimal result = NumberUtils.calculateRatio(5, 200000); | |
| // then | |
| assertThat(result).isEqualTo(BigDecimal.valueOf(0.003)); | |
| } | |
| @Test | |
| void should_calculateRatio_divide_by_0() { | |
| // when | |
| BigDecimal result = NumberUtils.calculateRatio(5, 0); | |
| // then | |
| assertThat(result).isEqualByComparingTo(BigDecimal.ZERO); | |
| } | |
| @Test | |
| void should_calculate_standard_deviation_from_a_list_of_values() { | |
| // given | |
| List<BigDecimal> givenValues = List.of( | |
| new BigDecimal("2.0"), | |
| new BigDecimal("7.0"), | |
| new BigDecimal("3.0"), | |
| new BigDecimal("12.0"), | |
| new BigDecimal("9.0") | |
| ); | |
| // when | |
| BigDecimal actualStandardDeviation = NumberUtils.getStandardDeviation(givenValues); | |
| // then | |
| BigDecimal expectedStandardDeviation = new BigDecimal("3.72").setScale(2, NumberUtils.ROUNDING_MODE); | |
| assertThat(actualStandardDeviation).isEqualTo(expectedStandardDeviation); | |
| } | |
| @Test | |
| void should_calculate_median_from_a_list_of_odd_number_of_values() { | |
| // given | |
| List<BigDecimal> givenValues = List.of( | |
| new BigDecimal("24.1"), | |
| new BigDecimal("25.0"), | |
| new BigDecimal("25.2"), | |
| new BigDecimal("25.6"), | |
| new BigDecimal("25.7"), | |
| new BigDecimal("26.1"), | |
| new BigDecimal("27.8") | |
| ); | |
| // when | |
| BigDecimal actualMedian = NumberUtils.getMedian(givenValues); | |
| // then | |
| BigDecimal expectedMedian = new BigDecimal("25.6").setScale(2, NumberUtils.ROUNDING_MODE); | |
| assertThat(actualMedian).isEqualTo(expectedMedian); | |
| } | |
| @Test | |
| void should_calculate_median_from_a_list_of_even_number_of_values() { | |
| // given | |
| List<BigDecimal> givenValues = List.of( | |
| new BigDecimal("24.1"), | |
| new BigDecimal("24.7"), | |
| new BigDecimal("25.0"), | |
| new BigDecimal("25.2"), | |
| new BigDecimal("25.6"), | |
| new BigDecimal("25.7"), | |
| new BigDecimal("26.1"), | |
| new BigDecimal("27.8") | |
| ); | |
| // when | |
| BigDecimal actualMedian = NumberUtils.getMedian(givenValues); | |
| // then | |
| BigDecimal expectedMedian = new BigDecimal("25.40").setScale(2, NumberUtils.ROUNDING_MODE); | |
| assertThat(actualMedian).isEqualTo(expectedMedian); | |
| }</pre> | |
| </div> | |
| </div> | |
| <div class="summary"> | |
| <p><strong>Changes:</strong> Converted Spock's when:/then:/expect:/given: blocks to JUnit @Test methods with comments. Replaced Groovy BigDecimal literals (2.0g) with new BigDecimal("2.0"). Used AssertJ assertThat() for all assertions. Method names use underscores instead of quoted strings.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| function toggleSection(header) { | |
| const content = header.nextElementSibling; | |
| const toggle = header.querySelector('.toggle'); | |
| content.classList.toggle('collapsed'); | |
| toggle.textContent = content.classList.contains('collapsed') ? '▶' : '▼'; | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment