Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/recruiting/pipeline_stage_test.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/recruiting/pipeline_stage_test.go |
| Original SHA-256 | f241b7b4ea773669f060c28f4c6eeb8586ee67d66f3d2aa478215c98c82072aa |
| Git blob SHA | 131bac057fe01265c8ea77ec8138280c282c18ca |
| Reading-copy SHA-256 | f241b7b4ea773669f060c28f4c6eeb8586ee67d66f3d2aa478215c98c82072aa |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / internal/modules/recruiting/pipeline_stage_test.go | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / internal/modules/recruiting/pipeline_stage_test.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓232 lines · 8.3 KB
package recruiting
import (
"errors"
"math/rand"
"strconv"
"testing"
)
// TestStageVocabularyMatchesMigration pins the Go ladder against the CHECK constraint in 0048 and the
// ordinals against rm_stage_ord. A value this code accepts and the database refuses is a 500.
func TestStageVocabularyMatchesMigration(t *testing.T) {
want := map[string]int{
"sourced": 1, "screened": 2, "submitted": 3, "interviewing": 4,
"offered": 5, "placed": 6, "rejected": -1, "withdrawn": -2,
}
if len(stageOrd) != len(want) {
t.Fatalf("stageOrd has %d entries, migration 0048 defines %d", len(stageOrd), len(want))
}
for s, o := range want {
if stageOrd[s] != o {
t.Errorf("rm_stage_ord(%q) is %d in 0048 but %d here", s, o, stageOrd[s])
}
}
if len(ladder) != 6 {
t.Fatalf("the ladder has %d rungs, want 6", len(ladder))
}
for i, s := range ladder {
if stageOrd[s] != i+1 {
t.Errorf("ladder position %d holds %q whose ordinal is %d", i+1, s, stageOrd[s])
}
}
// Terminal outcomes must sort BELOW every rung, or a rejection would read as further along than an
// offer everywhere the ordinal is compared.
for _, term := range []string{stageRejected, stageWithdrawn} {
for _, rung := range ladder {
if stageOrd[term] >= stageOrd[rung] {
t.Errorf("%q (%d) sorts at or above the rung %q (%d)", term, stageOrd[term], rung, stageOrd[rung])
}
}
}
}
// TestFunnelIsMonotonicForEveryPossibleInput is the property the whole funnel rests on.
//
// Whatever the distribution of high water marks, the count at each rung must be non increasing across
// the ladder. A funnel that widens is a funnel that is lying, and it is the single most common defect in
// recruiting dashboards. Fifty thousand random populations, including degenerate ones.
func TestFunnelIsMonotonicForEveryPossibleInput(t *testing.T) {
rng := rand.New(rand.NewSource(20260721))
for trial := 0; trial < 50000; trial++ {
n := rng.Intn(40)
marks := make([]int, n)
for i := range marks {
marks[i] = rng.Intn(6) + 1 // high water marks are always a rung, 1 to 6
}
f := funnelFrom(marks, n)
if len(f) != 6 {
t.Fatalf("funnel has %d stages, want 6", len(f))
}
for i := 0; i+1 < len(f); i++ {
if f[i+1].Count > f[i].Count {
t.Fatalf("funnel widened: %s=%d then %s=%d (marks %v)",
f[i].Stage, f[i].Count, f[i+1].Stage, f[i+1].Count, marks)
}
}
if n > 0 && f[0].Count != n {
t.Fatalf("the first rung counted %d of %d applications, every application has reached it", f[0].Count, n)
}
// Every conversion rate must land in [0,100] without clamping. A rate above 100 would mean more
// candidates left a stage than entered it.
for _, c := range conversionFrom(f) {
v, err := strconv.ParseFloat(c.Rate, 64)
if err != nil {
t.Fatalf("conversion %s to %s is not a number: %q", c.From, c.To, c.Rate)
}
if v < 0 || v > 100 {
t.Fatalf("conversion %s to %s = %s, outside [0,100] (marks %v)", c.From, c.To, c.Rate, marks)
}
}
}
}
// TestFunnelEmptyPopulationIsStable. A new client's first login must render a complete funnel of zeros
// rather than a missing chart or a divide by zero.
func TestFunnelEmptyPopulationIsStable(t *testing.T) {
f := funnelFrom(nil, 0)
if len(f) != 6 {
t.Fatalf("empty funnel has %d stages, want 6 so the chart shape is stable", len(f))
}
for _, s := range f {
if s.Count != 0 || s.Pct != "0.00" {
t.Errorf("stage %q = %d (%s), want 0 (0.00)", s.Stage, s.Count, s.Pct)
}
if s.Label == "" {
t.Errorf("stage %q has no label", s.Stage)
}
}
for _, c := range conversionFrom(f) {
if c.Rate != "0.00" {
t.Errorf("conversion %s to %s = %s on an empty population, want 0.00", c.From, c.To, c.Rate)
}
}
}
// TestFunnelAllPlacedIsFlat. If every application reached the top, every rung equals the total and every
// conversion is 100. This is the boundary the monotonicity check must not mistake for an error.
func TestFunnelAllPlacedIsFlat(t *testing.T) {
f := funnelFrom([]int{6, 6, 6}, 3)
for _, s := range f {
if s.Count != 3 || s.Pct != "100.00" {
t.Errorf("stage %q = %d (%s), want 3 (100.00)", s.Stage, s.Count, s.Pct)
}
}
for _, c := range conversionFrom(f) {
if c.Rate != "100.00" {
t.Errorf("conversion %s to %s = %s, want 100.00", c.From, c.To, c.Rate)
}
}
}
// TestPctIsExactDecimalNotFloat. One third must render as 33.33, not 33.32 or 33.34, and the value must
// be reproducible, because these figures feed an adverse impact report.
func TestPctIsExactDecimal(t *testing.T) {
for _, c := range []struct {
n, total int
want string
}{
{1, 3, "33.33"}, {2, 3, "66.67"}, {1, 1, "100.00"}, {0, 5, "0.00"},
{1, 0, "0.00"}, // no population is not a divide by zero
{7, 8, "87.50"}, {4, 5, "80.00"}, // the four fifths threshold itself
} {
if got := pctOf(c.n, c.total); got != c.want {
t.Errorf("pctOf(%d, %d) = %s, want %s", c.n, c.total, got, c.want)
}
}
}
// TestDispositionVocabularyMatchesMigration pins the Go codes against the CHECK constraint in 0054.
func TestDispositionVocabularyMatchesMigration(t *testing.T) {
inMigration := []string{
"not_qualified", "clearance_gap", "rate_mismatch", "location_mismatch", "client_declined",
"interview_performance", "offer_declined_by_client", "position_cancelled", "duplicate",
"candidate_withdrew", "candidate_unresponsive", "accepted_other_offer", "compensation", "other",
}
if len(dispositionCodes) != len(inMigration) {
t.Fatalf("the service knows %d codes, migration 0054 permits %d", len(dispositionCodes), len(inMigration))
}
for _, c := range inMigration {
if _, ok := dispositionCodes[c]; !ok {
t.Errorf("code %q is in migration 0054 but missing from the service", c)
}
}
}
// TestDispositionCodeMustMatchTheOutcome. Recording a candidate's withdrawal as an employer rejection
// would overstate the employer's rejection rate in precisely the report that rate exists for.
func TestDispositionCodeMustMatchTheOutcome(t *testing.T) {
cases := []struct {
code, stage string
ok bool
}{
{"not_qualified", stageRejected, true},
{"candidate_withdrew", stageWithdrawn, true},
{"other", stageRejected, true}, // permitted for either
{"other", stageWithdrawn, true},
{"not_qualified", stageWithdrawn, false}, // an employer reason on a candidate decision
{"accepted_other_offer", stageRejected, false},
{"made_up_code", stageRejected, false},
{"", stageRejected, false},
}
for _, c := range cases {
err := validDisposition(c.code, c.stage)
if c.ok && err != nil {
t.Errorf("validDisposition(%q, %q) refused a legitimate pairing: %v", c.code, c.stage, err)
}
if !c.ok {
if err == nil {
t.Errorf("validDisposition(%q, %q) accepted an invalid pairing", c.code, c.stage)
continue
}
if !errors.Is(err, ErrInvalid) {
t.Errorf("validDisposition(%q, %q) must unwrap to ErrInvalid so the handler returns 422", c.code, c.stage)
}
}
}
}
// TestNoDispositionCodeNamesAProtectedAttribute is a standing guard on the AEDT rules. The disposition
// vocabulary is the one place a protected attribute could plausibly be introduced by someone adding a
// well meaning reason code, and it would then flow straight into matching data.
func TestNoDispositionCodeNamesAProtectedAttribute(t *testing.T) {
forbidden := []string{
"race", "color", "religion", "sex", "gender", "national", "origin", "age", "older", "young",
"disab", "veteran", "pregnan", "marital", "sexual", "orientation", "genetic", "ethnic",
}
for code := range dispositionCodes {
for _, f := range forbidden {
if contains(code, f) {
t.Errorf("disposition code %q contains %q, which is a protected attribute or a proxy for one", code, f)
}
}
}
}
func contains(s, sub string) bool {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
}
// TestTerminalStagesAreClassified. isTerminalStage decides whether a reason code is demanded, so it must
// agree with the CHECK constraint in 0048 exactly.
func TestTerminalStagesAreClassified(t *testing.T) {
for _, s := range ladder {
if isTerminalStage(s) {
t.Errorf("%q is a rung on the ladder but is classified terminal", s)
}
}
for _, s := range []string{stageRejected, stageWithdrawn} {
if !isTerminalStage(s) {
t.Errorf("%q ends an application but is not classified terminal", s)
}
}
if isStage("archived") {
t.Error("an unknown stage was accepted as valid")
}
}