Conversation
The scenario under measurement is a task which kept its end date and changed its duration. A positive control with a moved end date runs beside it, so that a count of zero cannot be mistaken for a broken test rig. Measured on 92a91e9: the control counts one bar, the scenario counts none.
The task was compared with its baseline on end dates alone, so a task whose end date did not move got no baseline bar at all. A task which starts earlier and ends on the same day therefore takes longer than planned and is the one task which shows nothing, while its neighbours show two bars each. The bar is now drawn whenever the end date moved or the duration changed. The colours are unchanged: they still follow the end date, because that is what a schedule is judged by. A task which still ends on the planned day gets neither colour and is painted with the neutral one. The rule is extracted into a function so that it can be tested.
GanttPreviousState.createTasks() takes the duration with getDuration().getLength(), which truncates to whole units, and stores it as an int. Comparing that against getLength(timeUnit), which keeps the fraction, would have called a task changed whenever its duration had one -- and drawn a neutral bar for a task which did not move at all. Both sides are now the same whole number.
|
|
||
| private val DEVIATION_STYLES = listOf("later", "earlier", "milestone") | ||
|
|
||
| private class SceneTaskStub( |
There was a problem hiding this comment.
There is an existing test implementation in TaskRendererImplTest. I suggest extracting these test implementations into their own file and reusing in different tests, if that makes sense.
The chart tests live in ganttproject-tester, and TaskRendererImplTest, which has its own ITaskSceneTask implementation, is one of them. A test helper cannot be shared between ganttproject/src/test and ganttproject-tester/test: the latter depends on the main source set of :ganttproject only, so a class in ganttproject/src/test is not on its compile classpath. Pure move, no change to the test itself.
TaskRendererImplTest and BaselineBarCountTest each had a hand-written ITaskSceneTask. The eight members that neither test cares about were identical in both, and they now live once in TestSceneTask, next to TestPainter and the other chart test helpers. The members that the tests do care about could not be shared, because the two implementations answer them from different places: TaskRendererImplTest reads rowId and expand through to a live Task -- testVerticalPartitioningWithCollapsedTasks collapses the task after wrapping it -- while BaselineBarCountTest has no task manager at all and holds its geometry itself. They stay as two small subclasses. The base throws for an unimplemented member instead of returning null out of a property declared non-null, which is what TaskRendererImplTest's implementation did for color, end, activities and duration.
|
Done, with one deviation I should flag up front. The two implementations were in different Gradle modules. TaskRendererImplTest Rather than introduce a new sharing mechanism, I moved What could and could not be shared. Eight of the fourteen members were
So they are two small subclasses in the one file, One deliberate behaviour change. Evidence that no check got weaker. I extracted every Net effect: 89 insertions, 116 deletions. |
This replaces #2846, which I am closing.
You were right about the colours there. The end date is what a schedule is
judged by, so a task that gets longer or shorter while still meeting its
deadline should not be flagged as a delay. That half is dropped. The colours
in this PR are exactly the ones on master:
laterwhen the task now endslater than planned,
earlierwhen it ends sooner, decided by the end datealone.
What is left is a separate bug.
The bug. When a task keeps its end date but its duration changed,
renderBaselinereturns early and no baseline bar is drawn at all. The usersees nothing -- not a neutral bar, nothing -- even though the task no longer
matches its baseline.
Measured on master 92a91e9: a task with a baseline of 10 Aug + 5 days
(ending 15 Aug) that now runs 5 Aug + 10 days (also ending 15 Aug) draws
0 baseline bars where 1 is expected. The positive control -- the same
harness and the same task, with only the end date shifted -- draws 1 and is
green, so the zero is the finding and not a broken test.
This is independent of how the colours are chosen.
The change. +21/-10 lines of code in one file,
GanttChartSceneBuilder.java, in two places: the "should there be a bar, andwhich styles" decision moves out of
renderBaselineinto a staticgetBaselineStyles(...), and the guard becomesso a bar is drawn whenever anything changed, not only when the end date
moved. The styles are then added from the end date comparison exactly as
before. Durations are compared as the whole units the baseline stored, which
is the number
GanttPreviousState.createTasks()took from the task in thefirst place.
One consequence worth naming. A bar for a task that still ends on the
planned day carries neither
earliernorlater, soStyledPainterImplfalls through to
getPreviousTaskColor()-- the existing "Task remains onschedule" preference. On master that preference cannot reach a baseline bar
at all: there is a single place that creates a
previousStateTaskshape andit always adds one of the two deviation styles. This patch is what makes that
preference do something. That is read from the code; I did not check the
colour on screen.
Beyond this PR. My fork does this differently, since you have looked there
already: the single band became three. One compares end dates anchored at the
planned start, one compares durations anchored at today's start, and one compares
recorded hours against the original estimate -- that last one needs the effort
tracking and would do nothing here. It is a design change rather than a bug fix,
so this PR leaves master's single band as it is.
Tests.
BaselineBarCountTest.kt(2 tests) drives the productionGanttChartSceneBuilderthrough a hand-writtenInputApi, callsrender()and counts the shapes on the finished canvas whose style is
previousStateTask. That is the test that shows 0-vs-1 on master.BaselineStylesTest.kt(8 tests) pins the style decision, six of them nailingdown today's colour behaviour so it cannot drift. Full run on this branch:
BUILD SUCCESSFUL, 408 tests, 0 failures, 0 errors.
Negative control: taking just
&& currentDuration == baselineDurationbackout of the guard and changing nothing else turns 3 of the 10 new tests red,
and they are the 3 that were predicted -- the bar count test, and the two
"grew / shrank but still ends on the planned day" style tests. The other 7
stay green, which is right: they do not touch this case. Putting the
condition back makes all 10 green again.
Why a new PR rather than a push to #2846. Of the 9 tests on that branch,
not one tests this bug on its own: 4 hold under either semantics, 3 are purely
about the colours, and 2 mix the two in a single assertion. There was nothing
in it you could read as "this is the missing-bar fix", so a fresh small PR
seemed cleaner than force-pushing over a review you had already answered.