Aracılığıyla paylaş


Notebooklar için Birim Testi

Not defterlerinizin kodunun kalitesini ve tutarlılığını artırmaya yardımcı olmak için birim testi kullanabilirsiniz. Birim testi, işlevler gibi bağımsız kod birimlerini erken ve sık test etmeye yönelik bir yaklaşımdır. Bu, kodunuzla ilgili sorunları daha hızlı bulmanıza, kodunuzla ilgili yanlış varsayımları daha erken ortaya çıkarmanıza ve genel kodlama çalışmalarınızı kolaylaştırmanıza yardımcı olur.

Bu makale, işlevlerle temel birim testi giriş niteliğindedir. Birim testi sınıfları ve arabirimleri gibi gelişmiş kavramların yanı sırasaplamalarının kullanımı,sahteve testkullanılırken, not defterleri için birim testi yaparken de desteklenir. Bu makale,tümleştirme testi, sistem testi, kabul testiveya performans testi veya kullanılabilirlik testigibi işlevsel olmayan test yöntemleri gibi diğer test yöntemlerini de kapsamaz.

Bu makalede aşağıdakiler gösterilmektedir:

  • İşlevleri ve bunların birim testlerini düzenleme.
  • Python, R, Scala'daki işlevlerin yanı sıra SQL'de birim testi için iyi tasarlanmış kullanıcı tanımlı işlevler yazma.
  • Python, R, Scala ve SQL not defterlerinden bu işlevleri çağırma.
  • Python, R ve Scala'da, popüler test çerçeveleri kullanılarak; Python için pytest , R için testthat ve Scala için ScalaTest ile birim testleri nasıl yazılır. Ayrıca SQL kullanıcı tanımlı işlevlerini (SQL UDF'leri) birim testleri için SQL yazma.
  • Python, R, Scala ve SQL not defterlerinden bu birim testlerini çalıştırma.

Not

Azure Databricks, birim testlerinizi not defterinde yazmanızı ve çalıştırmanızı önerir. Web terminalinde bazı komutları çalıştırabilirsiniz ancak web terminalinde Spark desteğinin olmaması gibi daha fazla sınırlama vardır. Bkz. Azure Databricks web terminalinde kabuk komutlarını çalıştırma.

İşlevleri ve birim testlerini düzenleme

İşlevlerinizi ve bunların birim testlerini not defterleriyle düzenlemek için birkaç yaygın yaklaşım vardır. Her yaklaşımın avantajları ve zorlukları vardır.

Python, R ve Scala not defterleri için yaygın yaklaşımlar şunlardır:

  • İşlevleri ve bunların birim testlerini not defterleri dışında depolayın..
    • Avantajlar: Bu işlevleri not defterleriyle ve not defterleri dışından çağırabilirsiniz. Test çerçeveleri, testleri not defterleri dışında çalıştıracak şekilde daha iyi tasarlanmıştır.
    • Zorluklar: Bu yaklaşım Scala not defterleri için desteklenmez. Bu yaklaşım, izlenip korunacak dosya sayısını da artırır.
  • İşlevleri tek bir not defterinde ve birim testlerini ayrı bir not defterinde depolayın..
    • Avantajlar: Bu işlevlerin not defterleri arasında yeniden kullanılması daha kolaydır.
    • Zorluklar: İzlenip korunacak not defterlerinin sayısı artar. Bu işlevler not defterlerinin dışında kullanılamaz. Bu işlevlerin not defterleri dışında test edilmesi de daha zor olabilir.
  • İşlevleri ve bunların birim testlerini aynı deftere saklayın..
    • Avantajlar: İşlevler ve birim testleri, daha kolay izleme ve bakım için tek bir not defterinde depolanır.
    • Zorluklar: Bu işlevlerin not defterleri arasında yeniden kullanılması daha zor olabilir. Bu işlevler not defterlerinin dışında kullanılamaz. Bu işlevlerin not defterleri dışında test edilmesi de daha zor olabilir.

Databricks, Python ve R not defterleri için işlevlerin ve birim testlerinin not defterleri dışında depolanmasını önerir. Scala not defterleri için Databricks, tek bir not defterindeki işlevleri ve bunların birim testlerini ayrı bir not defterine eklemenizi önerir.

Databricks, SQL not defterleri için işlevleri şemalarınızda (veritabanları olarak da bilinir) SQL kullanıcı tanımlı işlevler (SQL UDF'leri) olarak depolamanızı önerir. Daha sonra bu SQL UDF'lerini ve bunların birim testlerini SQL not defterlerinden çağırabilirsiniz.

Yazma işlevleri

Bu bölümde, aşağıdakileri belirleyen basit bir örnek işlev kümesi açıklanmaktadır:

  • Veritabanında tablo bulunup bulunmadığı.
  • Tabloda bir sütunun bulunup bulunmadığı.
  • Bu sütundaki bir değer için bir sütunda kaç satır var?

Bu işlevlerin basit olması amaçlanmıştır, böylece işlevlere odaklanmak yerine bu makaledeki birim testi ayrıntılarına odaklanabilirsiniz.

En iyi birim testi sonuçlarını almak için işlevin tek bir tahmin edilebilir sonuç döndürmesi ve tek bir veri türünde olması gerekir. Örneğin, bir şeyin var olup olmadığını denetlemek için işlevin true veya false boole değeri döndürmesi gerekir. Var olan satır sayısını döndürmek için işlevin negatif olmayan bir tamsayı döndürmesi gerekir. İlk örnekte, bir şey yoksa false döndürmemeli, varsa da o şeyin kendisini döndürmemelidir. Benzer şekilde, ikinci örnekte de var olan satır sayısını veya satır yoksa false değerini döndürmemelidir.

Bu işlevleri python, R, Scala veya SQL'de mevcut bir Azure Databricks çalışma alanına aşağıdaki gibi ekleyebilirsiniz.

Piton

Aşağıdaki kodda,Databricks Git klasörlerini (Repos) ayarlama bir depo eklediğiniz ve deponun Azure Databricks çalışma alanınızda açık olduğu varsayılır.

oluşturun ve dosyaya aşağıdaki içeriği ekleyin. Bu makaledeki diğer örneklerde bu dosyanın myfunctions.pyolarak adlandırılması beklenmiştir. Kendi dosyalarınız için farklı adlar kullanabilirsiniz.

import pyspark
from pyspark.sql import SparkSession
from pyspark.sql.functions import col

# Because this file is not a Databricks notebook, you
# must create a Spark session. Databricks notebooks
# create a Spark session for you by default.
spark = SparkSession.builder \
                    .appName('integrity-tests') \
                    .getOrCreate()

# Does the specified table exist in the specified database?
def tableExists(tableName, dbName):
  return spark.catalog.tableExists(f"{dbName}.{tableName}")

# Does the specified column exist in the given DataFrame?
def columnExists(dataFrame, columnName):
  if columnName in dataFrame.columns:
    return True
  else:
    return False

# How many rows are there for the specified value in the specified column
# in the given DataFrame?
def numRowsInColumnForValue(dataFrame, columnName, columnValue):
  df = dataFrame.filter(col(columnName) == columnValue)

  return df.count()

R

Aşağıdaki kodda,Databricks Git klasörlerini (Repos) ayarlama bir depo eklediğiniz ve deponun Azure Databricks çalışma alanınızda açık olduğu varsayılır.

oluşturun ve dosyaya aşağıdaki içeriği ekleyin. Bu makaledeki diğer örneklerde bu dosyanın myfunctions.rolarak adlandırılması beklenmiştir. Kendi dosyalarınız için farklı adlar kullanabilirsiniz.

library(SparkR)

# Does the specified table exist in the specified database?
table_exists <- function(table_name, db_name) {
  tableExists(paste(db_name, ".", table_name, sep = ""))
}

# Does the specified column exist in the given DataFrame?
column_exists <- function(dataframe, column_name) {
  column_name %in% colnames(dataframe)
}

# How many rows are there for the specified value in the specified column
# in the given DataFrame?
num_rows_in_column_for_value <- function(dataframe, column_name, column_value) {
  df = filter(dataframe, dataframe[[column_name]] == column_value)

  count(df)
}

Scala

Aşağıdaki içeriklere sahip adlı myfunctions oluşturun. Bu makaledeki diğer örnekler, bu not defterinin myfunctionsolarak adlandırılmasını bekliyor. Kendi not defterleriniz için farklı adlar kullanabilirsiniz.

import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.functions.col

// Does the specified table exist in the specified database?
def tableExists(tableName: String, dbName: String) : Boolean = {
  return spark.catalog.tableExists(dbName + "." + tableName)
}

// Does the specified column exist in the given DataFrame?
def columnExists(dataFrame: DataFrame, columnName: String) : Boolean = {
  val nameOfColumn = null

  for(nameOfColumn <- dataFrame.columns) {
    if (nameOfColumn == columnName) {
      return true
    }
  }

  return false
}

// How many rows are there for the specified value in the specified column
// in the given DataFrame?
def numRowsInColumnForValue(dataFrame: DataFrame, columnName: String, columnValue: String) : Long = {
  val df = dataFrame.filter(col(columnName) === columnValue)

  return df.count()
}

SQL

Aşağıdaki kodda, Azure Databricks çalışma alanınızdan erişilebilen main adlı bir katalogda default adlı şemada üçüncü taraf örnek veri kümesinin elmas olduğu varsayılır. Kullanmak istediğiniz kataloğun veya şemanın adı farklıysa, aşağıdaki USE deyimlerinden birini veya ikisini de eşleşecek şekilde değiştirin.

bir SQL not defteri oluşturun ve bu yeni not defterine aşağıdaki içeriği ekleyin. Ardından not defterini bir kümeye ekleyin ve aşağıdaki SQL UDF'lerini belirtilen kataloğa ve şemaya eklemek için not defterini çalıştırın.

Not

SQL UDF'leri table_exists ve column_exists yalnızca Unity Kataloğu ile çalışır. Unity Kataloğu için SQL UDF desteği Genel Önizlemesürümündedir.

USE CATALOG main;
USE SCHEMA default;

CREATE OR REPLACE FUNCTION table_exists(catalog_name STRING,
                                        db_name      STRING,
                                        table_name   STRING)
  RETURNS BOOLEAN
  RETURN if(
    (SELECT count(*) FROM system.information_schema.tables
     WHERE table_catalog = table_exists.catalog_name
       AND table_schema  = table_exists.db_name
       AND table_name    = table_exists.table_name) > 0,
    true,
    false
  );

CREATE OR REPLACE FUNCTION column_exists(catalog_name STRING,
                                         db_name      STRING,
                                         table_name   STRING,
                                         column_name  STRING)
  RETURNS BOOLEAN
  RETURN if(
    (SELECT count(*) FROM system.information_schema.columns
     WHERE table_catalog = column_exists.catalog_name
       AND table_schema  = column_exists.db_name
       AND table_name    = column_exists.table_name
       AND column_name   = column_exists.column_name) > 0,
    true,
    false
  );

CREATE OR REPLACE FUNCTION num_rows_for_clarity_in_diamonds(clarity_value STRING)
  RETURNS BIGINT
  RETURN SELECT count(*)
         FROM main.default.diamonds
         WHERE clarity = clarity_value

Çağrı işlevleri

Bu bölümde, önceki işlevleri çağıran kod açıklanmaktadır. Bu işlevleri, örneğin, belirtilen değerin belirli bir sütun içinde bulunduğu tablodaki satır sayısını saymak için kullanabilirsiniz. Ancak, devam etmeden önce tablonun gerçekten var olup olmadığını ve sütunun bu tabloda gerçekten var olup olmadığını denetlemek istersiniz. Aşağıdaki kod bu koşulları denetler.

Önceki bölümde yer alan işlevleri Azure Databricks çalışma alanınıza eklediyseniz, bu işlevleri çalışma alanınızdan aşağıdaki gibi çağırabilirsiniz.

Piton

bir Python not defteri oluşturun ve not defterine aşağıdaki içeriği ekleyin. Tablo adı, şema (veritabanı) adı, sütun adı ve sütun değeri için değişken değerlerini gerektiği gibi değiştirin. Ardından not defterini bir kümeye ekleyin ve sonuçları görmek için not defterini çalıştırın.

from myfunctions import *

tableName   = "diamonds"
dbName      = "default"
columnName  = "clarity"
columnValue = "VVS2"

# If the table exists in the specified database...
if tableExists(tableName, dbName):

  df = spark.sql(f"SELECT * FROM {dbName}.{tableName}")

  # And the specified column exists in that table...
  if columnExists(df, columnName):
    # Then report the number of rows for the specified value in that column.
    numRows = numRowsInColumnForValue(df, columnName, columnValue)

    print(f"There are {numRows} rows in '{tableName}' where '{columnName}' equals '{columnValue}'.")
  else:
    print(f"Column '{columnName}' does not exist in table '{tableName}' in schema (database) '{dbName}'.")
else:
  print(f"Table '{tableName}' does not exist in schema (database) '{dbName}'.") 

R

bir R not defteri oluşturun ve not defterine aşağıdaki içeriği ekleyin. Tablo adı, şema (veritabanı) adı, sütun adı ve sütun değeri için değişken değerlerini gerektiği gibi değiştirin. Ardından not defterini bir kümeye ekleyin ve sonuçları görmek için not defterini çalıştırın.

library(SparkR)
source("myfunctions.r")

table_name   <- "diamonds"
db_name      <- "default"
column_name  <- "clarity"
column_value <- "VVS2"

# If the table exists in the specified database...
if (table_exists(table_name, db_name)) {

  df = sql(paste("SELECT * FROM ", db_name, ".", table_name, sep = ""))

  # And the specified column exists in that table...
  if (column_exists(df, column_name)) {
    # Then report the number of rows for the specified value in that column.
    num_rows = num_rows_in_column_for_value(df, column_name, column_value)

    print(paste("There are ", num_rows, " rows in table '", table_name, "' where '", column_name, "' equals '", column_value, "'.", sep = "")) 
  } else {
    print(paste("Column '", column_name, "' does not exist in table '", table_name, "' in schema (database) '", db_name, "'.", sep = ""))
  }

} else {
  print(paste("Table '", table_name, "' does not exist in schema (database) '", db_name, "'.", sep = ""))
}

Scala

Önceki myfunctions Scala not defteriyle aynı klasörde başka bir Scala not defteri oluşturun ve aşağıdaki içeriği bu yeni not defterine ekleyin.

Bu yeni not defterinin ilk hücresine, %run büyüsünü çağıran aşağıdaki kodu ekleyin. Bu büyü, myfunctions not defterinin içeriğini yeni not defteriniz için kullanılabilir hale getirir.

%run ./myfunctions

Bu yeni not defterinin ikinci hücresine aşağıdaki kodu ekleyin. Tablo adı, şema (veritabanı) adı, sütun adı ve sütun değeri için değişken değerlerini gerektiği gibi değiştirin. Ardından not defterini bir kümeye ekleyin ve sonuçları görmek için not defterini çalıştırın.

val tableName   = "diamonds"
val dbName      = "default"
val columnName  = "clarity"
val columnValue = "VVS2"

// If the table exists in the specified database...
if (tableExists(tableName, dbName)) {

  val df = spark.sql("SELECT * FROM " + dbName + "." + tableName)

  // And the specified column exists in that table...
  if (columnExists(df, columnName)) {
    // Then report the number of rows for the specified value in that column.
    val numRows = numRowsInColumnForValue(df, columnName, columnValue)

    println("There are " + numRows + " rows in '" + tableName + "' where '" + columnName + "' equals '" + columnValue + "'.")
  } else {
    println("Column '" + columnName + "' does not exist in table '" + tableName + "' in database '" + dbName + "'.")
  }

} else {
  println("Table '" + tableName + "' does not exist in database '" + dbName + "'.")
}

SQL

Aşağıdaki kodu önceki not defterindeki yeni bir hücreye veya ayrı bir not defterindeki hücreye ekleyin. Gerekirse şema veya katalog adlarını sizinkiyle eşleşecek şekilde değiştirin ve sonuçları görmek için bu hücreyi çalıştırın.

SELECT CASE
-- If the table exists in the specified catalog and schema...
WHEN
  table_exists("main", "default", "diamonds")
THEN
  -- And the specified column exists in that table...
  (SELECT CASE
   WHEN
     column_exists("main", "default", "diamonds", "clarity")
   THEN
     -- Then report the number of rows for the specified value in that column.
     printf("There are %d rows in table 'main.default.diamonds' where 'clarity' equals 'VVS2'.",
            num_rows_for_clarity_in_diamonds("VVS2"))
   ELSE
     printf("Column 'clarity' does not exist in table 'main.default.diamonds'.")
   END)
ELSE
  printf("Table 'main.default.diamonds' does not exist.")
END

Birim testleri yazın

Bu bölümde, bu makalenin başına doğru açıklanan işlevlerin her birini test eden kod açıklanmaktadır. İleride işlevlerde herhangi bir değişiklik yaparsanız, bu işlevlerin hala beklediğiniz gibi çalışıp çalışmadığını belirlemek için birim testlerini kullanabilirsiniz.

İşlevleri bu makalenin başına doğru Azure Databricks çalışma alanınıza eklediyseniz, bu işlevler için birim testlerini çalışma alanınıza aşağıdaki gibi ekleyebilirsiniz.

Piton

Deponuzdaki önceki test_myfunctions.py dosyasıyla aynı klasörde myfunctions.py adlı başka bir dosya oluşturun ve dosyaya aşağıdaki içeriği ekleyin. Varsayılan olarak, pytest test etmek için adları .py ile başlayan ya da test_ile biten _test dosyalarını arar. Benzer şekilde, varsayılan olarak yapılandırılmış olan pytest, adları test_ ile başlayan işlevi test etmek için bu dosyaların içine bakar.

Genel olarak, üretimdeki verilerle çalışan işlevlere karşı birim testleri en iyi yöntemdir. Bu özellikle verileri ekleyen, kaldıran veya başka bir şekilde değiştiren işlevler için önemlidir. Üretim verilerinizin birim testleriniz tarafından beklenmeyen yollarla tehlikeye atılmasını korumak için üretim dışı verilere karşı birim testleri çalıştırmanız gerekir. Yaygın yaklaşımlardan biri, üretim verilerine mümkün olduğunca yakın sahte veriler oluşturmaktır. Aşağıdaki kod örneği, birim testlerinin çalıştırılması için sahte veriler oluşturur.

import pytest
import pyspark
from myfunctions import *
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StructField, IntegerType, FloatType, StringType

tableName    = "diamonds"
dbName       = "default"
columnName   = "clarity"
columnValue  = "SI2"

# Because this file is not a Databricks notebook, you
# must create a Spark session. Databricks notebooks
# create a Spark session for you by default.
spark = SparkSession.builder \
                    .appName('integrity-tests') \
                    .getOrCreate()

# Create fake data for the unit tests to run against.
# In general, it is a best practice to not run unit tests
# against functions that work with data in production.
schema = StructType([ \
  StructField("_c0",     IntegerType(), True), \
  StructField("carat",   FloatType(),   True), \
  StructField("cut",     StringType(),  True), \
  StructField("color",   StringType(),  True), \
  StructField("clarity", StringType(),  True), \
  StructField("depth",   FloatType(),   True), \
  StructField("table",   IntegerType(), True), \
  StructField("price",   IntegerType(), True), \
  StructField("x",       FloatType(),   True), \
  StructField("y",       FloatType(),   True), \
  StructField("z",       FloatType(),   True), \
])

data = [ (1, 0.23, "Ideal",   "E", "SI2", 61.5, 55, 326, 3.95, 3.98, 2.43 ), \
         (2, 0.21, "Premium", "E", "SI1", 59.8, 61, 326, 3.89, 3.84, 2.31 ) ]

df = spark.createDataFrame(data, schema)

# Does the table exist?
def test_tableExists():
  assert tableExists(tableName, dbName) is True

# Does the column exist?
def test_columnExists():
  assert columnExists(df, columnName) is True

# Is there at least one row for the value in the specified column?
def test_numRowsInColumnForValue():
  assert numRowsInColumnForValue(df, columnName, columnValue) > 0

R

Deponuzdaki önceki test_myfunctions.r dosyasıyla aynı klasörde myfunctions.r adlı başka bir dosya oluşturun ve dosyaya aşağıdaki içeriği ekleyin. Varsayılan olarak, testthat, adları .r ile başlayan test dosyalarını test etmek için arar.

Genel olarak, üretimdeki verilerle çalışan işlevlere karşı birim testleri en iyi yöntemdir. Bu özellikle verileri ekleyen, kaldıran veya başka bir şekilde değiştiren işlevler için önemlidir. Üretim verilerinizin birim testleriniz tarafından beklenmeyen yollarla tehlikeye atılmasını korumak için üretim dışı verilere karşı birim testleri çalıştırmanız gerekir. Yaygın yaklaşımlardan biri, üretim verilerine mümkün olduğunca yakın sahte veriler oluşturmaktır. Aşağıdaki kod örneği, birim testlerinin çalıştırılması için sahte veriler oluşturur.

library(testthat)
source("myfunctions.r")

table_name   <- "diamonds"
db_name      <- "default"
column_name  <- "clarity"
column_value <- "SI2"

# Create fake data for the unit tests to run against.
# In general, it is a best practice to not run unit tests
# against functions that work with data in production.
schema <- structType(
  structField("_c0",     "integer"),
  structField("carat",   "float"),
  structField("cut",     "string"),
  structField("color",   "string"),
  structField("clarity", "string"),
  structField("depth",   "float"),
  structField("table",   "integer"),
  structField("price",   "integer"),
  structField("x",       "float"),
  structField("y",       "float"),
  structField("z",       "float"))

data <- list(list(as.integer(1), 0.23, "Ideal",   "E", "SI2", 61.5, as.integer(55), as.integer(326), 3.95, 3.98, 2.43),
             list(as.integer(2), 0.21, "Premium", "E", "SI1", 59.8, as.integer(61), as.integer(326), 3.89, 3.84, 2.31))

df <- createDataFrame(data, schema)

# Does the table exist?
test_that ("The table exists.", {
  expect_true(table_exists(table_name, db_name))
})

# Does the column exist?
test_that ("The column exists in the table.", {
  expect_true(column_exists(df, column_name))
})

# Is there at least one row for the value in the specified column?
test_that ("There is at least one row in the query result.", {
  expect_true(num_rows_in_column_for_value(df, column_name, column_value) > 0)
})

Scala

Önceki myfunctions Scala not defteriyle aynı klasörde başka bir Scala not defteri oluşturun ve aşağıdaki içeriği bu yeni not defterine ekleyin.

Yeni not defterinin ilk hücresine, %run büyüsünü çağıran aşağıdaki kodu ekleyin. Bu büyü, myfunctions not defterinin içeriğini yeni not defteriniz için kullanılabilir hale getirir.

%run ./myfunctions

İkinci hücreye aşağıdaki kodu ekleyin. Bu kod, birim testlerinizi tanımlar ve bunların nasıl çalıştırılacaklarını belirtir.

Genel olarak, üretimdeki verilerle çalışan işlevlere karşı birim testleri en iyi yöntemdir. Bu özellikle verileri ekleyen, kaldıran veya başka bir şekilde değiştiren işlevler için önemlidir. Üretim verilerinizin birim testleriniz tarafından beklenmeyen yollarla tehlikeye atılmasını korumak için üretim dışı verilere karşı birim testleri çalıştırmanız gerekir. Yaygın yaklaşımlardan biri, üretim verilerine mümkün olduğunca yakın sahte veriler oluşturmaktır. Aşağıdaki kod örneği, birim testlerinin çalıştırılması için sahte veriler oluşturur.

import org.scalatest._
import org.apache.spark.sql.types.{StructType, StructField, IntegerType, FloatType, StringType}
import scala.collection.JavaConverters._

class DataTests extends AsyncFunSuite {

  val tableName   = "diamonds"
  val dbName      = "default"
  val columnName  = "clarity"
  val columnValue = "SI2"

  // Create fake data for the unit tests to run against.
  // In general, it is a best practice to not run unit tests
  // against functions that work with data in production.
  val schema = StructType(Array(
                 StructField("_c0",     IntegerType),
                 StructField("carat",   FloatType),
                 StructField("cut",     StringType),
                 StructField("color",   StringType),
                 StructField("clarity", StringType),
                 StructField("depth",   FloatType),
                 StructField("table",   IntegerType),
                 StructField("price",   IntegerType),
                 StructField("x",       FloatType),
                 StructField("y",       FloatType),
                 StructField("z",       FloatType)
               ))

  val data = Seq(
                  Row(1, 0.23, "Ideal",   "E", "SI2", 61.5, 55, 326, 3.95, 3.98, 2.43),
                  Row(2, 0.21, "Premium", "E", "SI1", 59.8, 61, 326, 3.89, 3.84, 2.31)
                ).asJava

  val df = spark.createDataFrame(data, schema)

  // Does the table exist?
  test("The table exists") {
    assert(tableExists(tableName, dbName) == true)
  }

  // Does the column exist?
  test("The column exists") {
    assert(columnExists(df, columnName) == true)
  }

  // Is there at least one row for the value in the specified column?
  test("There is at least one matching row") {
    assert(numRowsInColumnForValue(df, columnName, columnValue) > 0)
  }
}

nocolor.nodurations.nostacks.stats.run(new DataTests)

Not

Bu kod örneği ScalaTest'te test FunSuite stilini kullanır. Diğer kullanılabilir test stilleri için bkz. Projeniz için test stilleri seçme.

SQL

Birim testleri eklemeden önce, genel olarak, üretimdeki verilerle çalışan işlevlere karşı birim testlerini çalıştırmanın en iyi yöntem olduğunu bilmeniz gerekir. Bu özellikle verileri ekleyen, kaldıran veya başka bir şekilde değiştiren işlevler için önemlidir. Üretim verilerinizin birim testleriniz tarafından beklenmeyen yollarla tehlikeye atılmasını korumak için üretim dışı verilere karşı birim testleri çalıştırmanız gerekir. Yaygın yaklaşımlardan biri, tablo yerine görünümlerde birim testleri çalıştırmaktır.

Görünüm oluşturmak için, CREATE VIEW komutunu önceki not defterindeki yeni bir hücreden veya ayrı bir not defterinden çağırabilirsiniz. Aşağıdaki örnekte, mainadlı bir katalogda default adlı bir şemada (veritabanı) diamonds adlı bir tablonuz olduğu varsayılır. Bu adları gerektiği gibi kendi adlarınızla eşleşecek şekilde değiştirin ve ardından yalnızca bu hücreyi çalıştırın.

USE CATALOG main;
USE SCHEMA default;

CREATE VIEW view_diamonds AS
SELECT * FROM diamonds;

Görünümü oluşturduktan sonra, aşağıdaki SELECT deyimlerinin her birini önceki not defterindeki kendi yeni hücresine veya ayrı bir not defterindeki kendi yeni hücresine ekleyin. Adları gerektiği gibi kendi adlarınızla eşleşecek şekilde değiştirin.

SELECT if(table_exists("main", "default", "view_diamonds"),
          printf("PASS: The table 'main.default.view_diamonds' exists."),
          printf("FAIL: The table 'main.default.view_diamonds' does not exist."));

SELECT if(column_exists("main", "default", "view_diamonds", "clarity"),
          printf("PASS: The column 'clarity' exists in the table 'main.default.view_diamonds'."),
          printf("FAIL: The column 'clarity' does not exists in the table 'main.default.view_diamonds'."));

SELECT if(num_rows_for_clarity_in_diamonds("VVS2") > 0,
          printf("PASS: The table 'main.default.view_diamonds' has at least one row where the column 'clarity' equals 'VVS2'."),
          printf("FAIL: The table 'main.default.view_diamonds' does not have at least one row where the column 'clarity' equals 'VVS2'."));

Birim testlerini çalıştırma

Bu bölümde, önceki bölümde kodladığınız birim testlerinin nasıl çalıştırıldığı açıklanmaktadır. Birim testlerini çalıştırdığınızda, hangi birim testlerinin geçirildiğini ve başarısız olduğunu gösteren sonuçlar alırsınız.

Önceki bölümden birim testlerini Azure Databricks çalışma alanınıza eklediyseniz, bu birim testlerini çalışma alanınızdan çalıştırabilirsiniz. Bu birim testlerini ya el ile ya da bir zamanlamaya göre çalıştırabilirsiniz.

Piton

Deponuzdaki önceki test_myfunctions.py dosyasıyla aynı klasörde bir Python not defteri oluşturun ve aşağıdaki içeriği ekleyin.

Yeni not defterinin ilk hücresine aşağıdaki kodu ekleyin ve ardından %pip büyüsünü çağıran hücreyi çalıştırın. Bu işlem pytestyükler.

%pip install pytest

İkinci hücreye aşağıdaki kodu ekleyin ve hücreyi çalıştırın. Sonuçlar hangi birim testlerinin geçtiğini ve başarısız olduğunu gösterir.

import pytest
import sys

# Skip writing pyc files on a readonly filesystem.
sys.dont_write_bytecode = True

# Run pytest.
retcode = pytest.main([".", "-v", "-p", "no:cacheprovider"])

# Fail the cell execution if there are any test failures.
assert retcode == 0, "The pytest invocation failed. See the log for details."

R

Deponuzdaki önceki test_myfunctions.r dosyasıyla aynı klasörde bir R not defteri oluşturun ve aşağıdaki içeriği ekleyin.

İlk hücreye aşağıdaki kodu ekleyin ve ardından install.packages işlevini çağıran hücreyi çalıştırın. Bu işlev testthatyükler.

install.packages("testthat")

İkinci hücreye aşağıdaki kodu ekleyin ve ardından hücreyi çalıştırın. Sonuçlar hangi birim testlerinin geçtiğini ve başarısız olduğunu gösterir.

library(testthat)
source("myfunctions.r")

test_dir(".", reporter = "tap")

Scala

Önceki bölümden not defterinde birinci ve sonra ikinci hücreleri çalıştırın. Sonuçlar hangi birim testlerinin geçtiğini ve başarısız olduğunu gösterir.

SQL

Önceki bölümde yer alan not defterindeki üç hücrenin her birini çalıştırın. Sonuçlar, her birim testinin başarılı mı yoksa başarısız mı olduğunu gösterir.

Birim testlerinizi çalıştırdıktan sonra görünüme artık ihtiyacınız yoksa görünümü silebilirsiniz. Bu görünümü silmek için, aşağıdaki kodu önceki not defterlerinden birinin içindeki yeni bir hücreye ekleyebilir ve sonra yalnızca bu hücreyi çalıştırabilirsiniz.

DROP VIEW view_diamonds;

Bahşiş

Not defteri çalıştırmalarınızın sonuçlarını (birim testi sonuçları dahil) kümenizin sürücü günlüklerindegörüntüleyebilirsiniz. Kümenizin günlük teslimiiçin de bir konum belirtebilirsiniz.

Kodunuz her değiştiğinde birim testlerinizi otomatik olarak çalıştırmak için GitHub Actions gibi sürekli tümleştirme ve sürekli teslim veya dağıtım (CI/CD) sistemi ayarlayabilirsiniz. Örneğin,not defterleri için Yazılım mühendisliği en iyi yöntemleri bölümünde GitHub Actions'ın kapsamına bakın.

Ek kaynaklar

pytest

testthat

  • Giriş sayfasının test edin
  • İşlev başvurusu test

ScalaTest

SQL