Assertions

Definisce delle aspettative sui dati che possone essere verificate su una o più variabili generando report sulle violazioni trovate.

Importante

Se è attivo un filtro, l’elaborazione verrà limitata ai casi attivi.

assertions

assertions definisce la configurazione generale delle asserzioni.

Metodi:

  • vars: varlist1, varlist2: definisce le variabili aggiuntive che devono comparire nelle liste
  • list: true|false: attiva (default) o disattiva il listato dei casi
  • ok: true|false: mostra (default) o nasconde le righe relative ai dati corretti
  • fail: :continue|:stop|:abort: azione da intraprendere in caso di violazione: continue continua l’esecuzione, :stop interrompe lo script, :abort interrompe lo script senza listare i casi (default :continue)
  • maxid: n: numero di id di riga da mostrare (default 0)
  • save: filename: salva i report generati in un file xlsx (da utilizzare alla fine dopo il check dei dati). Ogni check verrà salvato in un foglio diverso.
  • config: accetta un hash o un blocco per la definizione delle proprietà
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
assertions.vars :ser_no, :mcr

assertions.fail :abort

assertions.config list: false, ok: false, maxid: 5

assertions.config do
  list false
  ok false
  maxid 5
end

assertions.save "cleaning"

assert

assert viene usato per definire un gruppo di regole che costituisce un’asserzione e gli eventuali risolutori (solver) dei problemi. E’ anche possibile concatenare tutti i metodi e assegnare l’asserzione a una variabile.

Argomenti:

  • :name: un simbolo con il nome dell’asserzione
  • "description": la descrizione
  • &block: il blocco di codice (do...end) che contiene le regole di validazione dei dati. In alternativa è possibile concatenare le istruzioni
1
2
3
4
5
6
assert :check_valid_int, "Deve essere un numero tra 1 e 10 senza valori mancanti" do
  between(1,10).solver :value, 0
  not_null.solver :prop
end

r1 = assert(:id_rule, "L'ID deve essere un intero senza duplicati").integer.uniq

L’asserzione viene poi richiamata e utilizzata tramite l’istruzione assert(name) o direttamente attraverso la variabile a cui era stata assegnata.

check

Il metodo check verifica l’asserzione rispetto a una o più variabili.

Argomenti:

  • var|varlist: la variabile o l’elenco di variabili da validare
  • var1|[varlist1] => var2|[varlist2]: la variabile o l’elenco di variabili da validare e la variabile o l’elenco di variabili necessarie per la validazione dell’asserzione (per es. per le recole fzdep e expr)
1
2
3
assert(:check_valid_int).check :d1, :d5

r1.check :ser_no
1
2
3
4
5
assert(:check1, "Non deve avere blank e valori non etichettati") do
  levels.solver :value, 9
  not_null.solver :rnd
end
assert(:check1).check :d1, :d5
1
2
 assert(:chk1).expr("$0>$1+$2").check :v1 => [:v10, :v20]
 assert(:chk2).fzdep.check [:city, :street] => :zip

Output testuale:

_images/assertions1.png

Output xlsx:

_images/assertions2.png

stop

Il metodo stop sostituisce il metodo check, provocando l’interruzione dello script in caso di violazione.

abort

Il metodo abort sostituisce il metodo check, provocando l’interruzione dello script in caso di violazione e omettendo la lista dei casi con violazioni.

flag

Il metodo flag crea per ciascuna variabile controllata, una nuova variabile che identifica i casi che contengono le violazioni.

Argomenti:

  • :root|"name"|[namelist]: un simbolo con la radice dei nomi da creare (default flag_), il nome per una sola variabile o un elenco di nomi
1
2
3
4
5
6
7
assert(:check_valid_int).check(:d1, :d5).flag                     # => "flag_d1", "flag_d5"

assert(:check_valid_int).check(:d1, :d5).flag [:err_d1, :err_d5]  # => "err_d1", "err_d5"

assert(:check_valid_int).check(:d1, :d5).flag :fl_, 9             # => "fl_d1", "fl_d5"

assert(:check_valid_int).check(:d1).flag "x1"                     # => "x1"

solve

solve risolve i problemi evidenziati. Per almeno una regola deve essere stato definito un solver. I solver vengono eseguiti nella sequenza in cui sono stati dichiarati.

Argomenti:

  • :seed => number permette ai solver basati su funzioni aleatorie di riprodurre, a parità di condizioni, gli stessi risultati
1
2
3
assert(:check_valid_int).check(:d1, :d5).solve

assert(:check_valid_int).check(:d1, :d5).solve :seed => 1234

Regole

Ciascuna asserzione è composta da una o più regole.

base

La variabile deve avere come base i casi definiti dall’espressione specificata. Verifica sia i casi che dovrebbero avere un valore, ma sono blank, sia i casi che hanno un valore, ma dovrebbero esser blank.

Argomenti:

  • expr: un’espressione filtro
1
base :target => [1,2]

valid_when

La variabile deve essere valida quando è valida l’espressione specificata. Verifica i casi che dovrebbero avere un valore, ma sono blank.

Argomenti:

  • expr: un’espressione filtro
1
valid_when :target => [1,2]

not_null o notnull

La variabile non deve avere casi mancanti.

Argomenti:

  • expr: (opzionale) un’espressione filtro
1
2
3
not_null

not_null :target => [1,2]

null

La variabile non deve contere nessun valore.

Argomenti:

  • expr: (opzionale) un’espressione filtro
1
2
3
null

null :target => [3,4]

min

La variabile deve avere valori superiori o uguali al valore minimo indicato. I casi mancanti sono ignorati.

Argomenti:

  • value: il valore minimo
1
min 1

max

La variabile deve avere valori inferiori o uguali al valore massimo indicato. I casi mancanti sono ignorati.

Argomenti:

  • value: il valore massimo
1
max 15

values

La variabile deve avere uno dei valori indicati. I casi mancanti sono ignorati.

Argomenti:

  • valuelist: la lista dei valori validi
  • :ic => true|false: ignora maiuscolo/minuscolo (default false)
1
2
values 1,2,6,8
values "va", "MI", :ic => true

between

La variabile deve avere valori compresi tra il valore minimo e il valore massimo indicati. I valori indicati devo essere interi. I casi mancanti sono ignorati.

Argomenti:

  • min, max: il valore minimo e il valore massimo
1
between 1,10

range

La variabile deve avere valori compresi tra il valore minimo e il valore massimo indicati. I valori indicati devo essere specificati come numeri decimali: 1.0, 2.9, 3.25. I casi mancanti sono ignorati.

Argomenti:

  • min.0, max.0, ndec: il valore minimo (float), il valore massimo (float) e (opzionale) il numero di decimali
1
2
3
range 2.5, 5.0

range 2.5, 5.0, 3

levels

La variabile deve avere valori corrispondenti ai codici dei livelli definiti della variabile. I casi mancanti sono ignorati.

type

La variabile deve contenere valori del tipo di dato indicato. I casi mancanti sono ignorati.

Argomenti:

  • :type: un simbolo con il tipo di dato: :integer, :float, :string
1
type :integer

uniq

La variabile deve contenere valori univoci. I casi mancanti sono ignorati.

sequence

La variabile deve contenere valori crescenti (o decrescenti). I casi mancanti sono ignorati.

Argomenti:

  • :d: (opzionale) discendente
1
2
3
sequence

sequence :d

upcase

La variabile deve avere tutti i caratteri in maiuscolo. I casi mancanti sono ignorati.

downcase

La variabile deve avere tutti i caratteri in minuscolo. I casi mancanti sono ignorati.

positive

La variabile deve avere tutti i valori positivi. I casi mancanti sono ignorati.

negative

La variabile deve avere tutti i valori negativi. I casi mancanti sono ignorati.

even

La variabile deve avere tutti i valori pari. I casi mancanti sono ignorati.

odd

La variabile deve avere tutti i valori dispari. I casi mancanti sono ignorati.

equal

Testa l’uguaglianza tra due variabili.

Nel metodo check devono essere forniti i due elenchi di variabili: var1|[varlist1] => var2|[varlist2].

1
2
assert(:chk1).equal.check :x5 => :d5
assert(:chk2).equal.check :x5 => :d5, :r5 => :d5

fzdep

Testa la dipendenza funzionale tra due variabili o due gruppi di variabili: A -> B. Se due record hanno lo stesso valore per A, allora devono avere lo stesso valore per B. I casi con valore mancante in una delle variabili di sinistra sono ignorati.

Nel metodo check devono essere forniti i due elenchi di variabili: var1|[varlist1] => var2|[varlist2].

1
2
3
assert(:chk1).fzdep.check :city => :prov
assert(:chk2).fzdep.check :zip => [:prov, :city]
assert(:chk3).fzdep.check [:city, :street] => :zip

expr

Testa l’espressione indicata.

All’interno dell’espressione è possibile utilizzare i segnaposti $# per le variabili che verranno inserite al momento del check. $0 è la variabile da validare, $1, $2, ecc. le restanti variabili.

All’interno dell’espressione è possibile utilizzare direttamente dei nomi di variabile.

Nel metodo check deve essere anche fornito l’elenco di variabili che costituiscono gli argomenti dell’espressione: var => var2|[varlist2].

1
2
3
4
5
6
7
8
assert(:expr1).expr("$0>$1").check :v1 => :v10
assert(:expr2).expr("$0*2>$1").check :v1 => :v10
assert(:expr3).expr("$0*2>v10").check :v1

assert(:expr3).expr("$0+$1>$2").check :v1 => [:v10, :v20]
assert(:expr4).expr("$0>$1*$2").check :v2 => [:v11, :v12], :v3 => [:v21, :v22]

assert(:expr5).expr("$0=UPCASE($0)").check :name

Risolutori

Il metodo solver definisce il solver per ciascuna regola. E’ possibile definire un solver solo per alcune regole o non definirne affatto.

Argomenti:

  • :solver_name: un simbolo con il nome del solver
  • args: l’eventuale lista di argomenti specifici del solver
  • :solver_name2: per alcune regole è possibile definire un secondo solver: un simbolo con il nome del secondo solver
  • args2: l’eventuale lista di argomenti specifici del secondo solver
1
2
3
levels.solver :value, 9

base(:gender => 2).solver :prop, :value, 9

nil

Assegna nil (blank) alla variabile.

1
between(1,10).solver :nil

value

Assegna il valore indicato alla variabile.

Argomenti:

  • value: il valore
1
between(1,10).solver :value, 0

rnd

Assegna un valore random tra quelli indicati.

Argomenti:

  • :levels|list|range: (opzionale) i codici dei livelli (default) o un intervallo di valori o una lista di valori
  • ndec: (opzionale) il numero di decimali
1
2
3
4
5
6
7
8
9
between(1,10).solver :rnd           # equivale a :levels

between(1,10).solver :rnd, :levels

between(1,10).solver :rnd, [3,5,7]

between(1,10).solver :rnd, 7..10

range(10.0,20.0).solver :rnd, 15.5..17.9, 3

prop

Assegna un valore secondo le proporzioni indicate. Se non è indicato alcun argomento, vengono utilizzatele distribuzioni di frequenze della variabile. Se è attivo un peso, vengono utilizzate le distribuzioni pesate.

Argomenti:

  • {value1 => prob1, value2 => prob2,...}: (opzionale) un hash con i valori da imputare e le probabilità di assegnazione. Le probabilità vengono riproporzionate a uno.
1
2
3
4
5
6
7
values(1,2).solver :prop

values(1,2).solver :prop, {1 => 0.33, 2 => 0.66}

values(1,2).solver :prop, {1 => 1, 2 => 2}

values(1,2).solver :prop, {1 => 33, 2 => 66}

drop

Elimina i record che contengono le violazioni.

1
between(1,10).solver :drop

stop

Interrompe l’esecuzione dello script in caso di violazione.

1
between(1,10).solver :stop

abort

Interrompe l’esecuzione dello script in caso di violazione senza listare i casi con errori.

1
between(1,10).solver :abort

Asserzioni predefinite

pTabs2 definisce alcune asserzioni di uso comune.

  • :chk_notnull: Variable must have values
    • rules: notnull
    • solvers: prop
  • :chk_uniq: Variable must have unique values
    • rules: uniq
    • solvers: drop
  • :chk_notdup: Variable must be full and with unique values
    • rules: notnull, uniq
    • solvers: drop
  • :chk_seq: Variable must be full and with ordinated values
    • rules: notnull, sequence
    • solvers: drop
  • :chk_null: Variable must have no values
    • rules: null
    • solvers: nil
  • :chk_dummy: It’s a dummy variable
    • rules: values(0,1)
  • :chk_equal: It’s equal to another variable
    • rules: expr("$0=$1")
  • :chk_levels: Variable must have code levels
    • rules: levels
    • solvers: prop
  • :chk_notover: Overlapped variables
    • rules: expr("NVALID($0,$1)<=1")
  • :chk_any: Missing values in both variables
    • rules: expr("NVALID($0,$1)>=1")
  • :chk_int: Variable must contain integer values
    • rules: type(:integer)
  • :chk_flt: Variable must contain float values
    • rules: type(:float)
  • :chk_str: Variable must contain string values
    • rules: type(:string)
1
2
3
4
5
6
7
assert(:chk_dummy).check s(:d7_,10)

assert(:chk_seq).check :ser_no

assert(:chk_notdup).check(:ser_no).solve

assert(:chk_equal).check :x101 => :v101

check_base, check_all

Le funzioni check_all e check_base permetto di eseguire più sinteticamente due comuni operazioni di controllo sui dati:

  • check_all varlist controlla che le variabili non contengano valori mancanti (utilizza la regola notnull)
  • check_base varlist, expression controlla che la base delle variabili sia conforme all’espressione indicata (utilizza la regola base)
1
2
3
4
check_all :v1, :v2

check_base s(:qv10_,1..7), :v11, :v12, :v100 => 1
check_base s(:qv10_,1..7), :v11, :v12, "v100=1"

if_not

if_not o ifnot è una variante di assert usata con i metodi stop e abort per interrompere, sollevando un errore, l’esecuzione dello script al verificarsi della violazione di un’asserzione.
Non richiede l’inserimento di un nome per l’asserzione, ma è possibile utilizzarlo con le asserzioni predefinite.
abort non lista i casi con le violazioni.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if_not.notnull.max(99).stop :price1, :price2

ifnot.values(2).abort :wave

if_not(:chk_notdup).stop :ser_no

if_not.equal.abort :x101 => :v101

if_not(:chk_notover).stop :v1 => :v2

if_not(:chk_any).stop :v1 => :v2