Opsi anotasi

Selesai

Ada beberapa opsi yang umum untuk semua anotasi; di modul terakhir, Anda belajar tentang opsi success_message dan failure_message. Dalam modul ini, kita membahas tiga opsi lagi yang dapat diterapkan pada anotasi dan bagaimana mereka dapat digunakan.

name

Opsi name ini digunakan untuk mengelompokkan berbagai instans kelas anotasi yang mewakili anotasi yang sama secara bersama-sama. Opsi ini digunakan untuk mencegah pesan ditampilkan beberapa kali ketika tidak perlu. Mari kita pertimbangkan contoh berikut: maximum fungsi memanggil fungsi Python max untuk memeriksa apakah siswa mengidentifikasi maksimum dengan benar, tetapi satu pesan keberhasilan dicetak untuk setiap input yang diuji fungsi.

>>> max_ref = []
>>> def maximum(l, track=False):
...     m = max(l)
...     if track:
...         max_ref.append(pybryt.Value(
...             m,
...             success_message="Found the max!", 
...             failure_message="Did not find the max",
...         ))
...     return m
>>> test_lists = [[1, 2, 3], [-1, 0, 1], [10, -4, 2, 0], [1]]
>>> for test_list in test_lists:
...     maximum(test_list, track=True)
>>> max_ref = pybryt.ReferenceImplementation("maximum", max_ref)
>>> with pybryt.check(max_ref):
...     for test_list in test_lists:
...         maximum(test_list)
REFERENCE: maximum
SATISFIED: True
MESSAGES:
  - Found the max!
  - Found the max!
  - Found the max!
  - Found the max!

Masalah dengan fungsi ini sederhana: anotasi yang dibuat di setiap pengujian pada dasarnya memeriksa hal yang sama, apakah siswa mengembalikan nilai yang benar. Memiliki pesan yang sama yang dicetak beberapa kali membuatnya tampak seperti anotasi menguji kondisi yang berbeda dan mengacaukan laporan yang dihasilkan oleh PyBryt. Kita dapat menutup semua pesan ini bersama-sama dengan menamai anotasi yang dibuat dalam fungsi maximum:

>>> max_ref = []
>>> def maximum(l, track=False):
...     m = max(l)
...     if track:
...         max_ref.append(pybryt.Value(
...             m,
...             name="list-maximum",
...             success_message="Found the max!", 
...             failure_message="Did not find the max",
...         ))
...     return m
>>> test_lists = [[1, 2, 3], [-1, 0, 1], [10, -4, 2, 0], [1]]
>>> for test_list in test_lists:
...     maximum(test_list, track=True)
>>> max_ref = pybryt.ReferenceImplementation("maximum", max_ref)
>>> with pybryt.check(max_ref):
...     for test_list in test_lists:
...         maximum(test_list)
REFERENCE: maximum
SATISFIED: True
MESSAGES:
  - Found the max!

Sekarang, kita dapat melihat bahwa pesan hanya dicetak sekali.

Ketika PyBryt menciutkan anotasi ke dalam satu pesan, itu hanya menampilkan pesan keberhasilan jika semua anotasi dalam grup nama terpenuhi. Jika ada pengujian dalam grup yang gagal, pengujian akan menampilkan pesan kegagalan sebagai gantinya. Mari kita perkenalkan bug untuk maximum menunjukkan:

>>> def maximum(l):
...     if len(l) % 2 == 0:
...         m = min(l)
...     else:
...         m = max(l)
...     return m
>>> with pybryt.check(max_ref):
...     for test_list in test_lists:
...         maximum(test_list)
REFERENCE: maximum
SATISFIED: False
MESSAGES:
  - Did not find the max

limit

Opsi limit memungkinkan Anda mengontrol berapa banyak salinan anotasi bernama yang disertakan dalam implementasi referensi. Opsi ini membantu kasus di mana fungsi yang membangun anotasi digunakan kembali berkali-kali selama penugasan. Kasus di mana beberapa pengujian awal cukup untuk memeriksa validitas implementasi dengan mengurangi ukuran implementasi referensi itu sendiri.

Mari kita ilustrasikan ini menggunakan fungsi kita maximum . Di sini, kami menggunakan implementasi serupa dengan referensi sebelumnya tetapi diatur limit ke lima anotasi dan mengujinya pada beberapa daftar input.

>>> max_ref = []
>>> def maximum(l, track=False):
...     m = max(l)
...     if track:
...         max_ref.append(pybryt.Value(
...             m,
...             name="list-maximum",
...             limit=5,
...             success_message="Found the max!", 
...             failure_message="Did not find the max",
...         ))
...     return m
>>> for _ in range(1000):
...     test_list = np.random.normal(size=100)
...     maximum(test_list, track=True)
>>> print(f"Annotations created: {len(max_ref)}")
>>> max_ref = pybryt.ReferenceImplementation("maximum", max_ref)
>>> print(f"Annotations in reference: {len(max_ref.annotations)}")
Annotations created: 1000
Annotations in reference: 5

Seperti yang Anda lihat, panjang max_ref.annotations adalah 5 meskipun 1.000 anotasi disertakan dalam daftar yang diteruskan ke konstruktor.

group

Opsi group ini mirip dengan opsi name karena digunakan untuk mengelompokkan anotasi bersama-sama, tetapi anotasi ini tidak selalu mewakili "anotasi yang sama"; sebaliknya, anotasi tersebut dikelompokkan menjadi potongan yang bermakna sehingga bagian referensi tertentu dapat diperiksa satu per satu, bukan sekaligus. Opsi ini dapat berguna dalam membangun tugas dengan beberapa pertanyaan di PyBryt.

Misalnya, pertimbangkan tugas yang meminta siswa untuk menerapkan mean fungsi dan median . Anda dapat membaginya menjadi dua pertanyaan seperti berikut:

# Question 1
mean_ref = []

def mean(l, track=False):
    size = len(l)
    if track:
        mean_ref.append(pybryt.Value(
            size,
            name="len",
            group="mean",
            success_message="Determined the length of the list",
        ))

    m = sum(l) / size
    if track:
        mean_ref.append(pybryt.Value(
            m,
            name="mean",
            group="mean",
            success_message="Calculated the correct mean of the list",
            failure_message="Did not find the correct mean of the list",
        ))

    return m

# Question 2
median_ref = []

def median(l, track=True):
    sorted_l = sorted(l)
    if track:
        median_ref.append(pybryt.Value(
            sorted_l,
            name="sorted",
            group="median",
            success_message="Sorted the list",
        ))
    
    size = len(l)
    if track:
        mean_ref.append(pybryt.Value(
            size,
            name="len",
            group="median",
            success_message="Determined the length of the list",
        ))

    middle = size // 2
    is_set_size_even = size % 2 == 0

    if is_set_size_even:
        m = (sorted_l[middle - 1] + sorted_l[middle]) / 2
    else:
        m = sorted_l[middle]

    if track:
        mean_ref.append(pybryt.Value(
            m,
            name="mean",
            group="mean",
            success_message="Calculated the correct mean of the list",
            failure_message="Did not find the correct mean of the list",
        ))

    return m

test_lists = [[1, 2, 3], [-1, 0, 1], [10, -4, 2, 0], [1]]
for test_list in test_lists:
    mean(test_list, track=True)
    median(test_list, track=True)

assignment_ref = pybryt.ReferenceImplementation("mean-median", [*mean_ref, *median_ref])

Dengan referensi yang dibangun seperti dalam contoh sebelumnya, kita dapat memberi siswa kesempatan untuk memeriksa pekerjaan mereka pada setiap pertanyaan individu sebelum melanjutkan ke pertanyaan berikutnya dengan memberi tahu PyBryt kelompok anotasi mana yang perlu dipertimbangkan:

>>> with pybryt.check(assignment_ref, group="mean"):
...     for test_list in test_lists:
...         mean(test_list)
REFERENCE: mean-median
SATISFIED: True
MESSAGES:
  - Determined the length of the list
  - Calculated the correct mean of the list
>>> with pybryt.check(assignment_ref, group="median"):
...     for test_list in test_lists:
...         median(test_list)
REFERENCE: mean-median
SATISFIED: True
MESSAGES:
  - Determined the length of the list
  - Sorted the list
>>> with pybryt.check(assignment_ref):
...     for test_list in test_lists:
...         mean(test_list)
...         median(test_list)
REFERENCE: mean-median
SATISFIED: True
MESSAGES:
  - Determined the length of the list
  - Calculated the correct mean of the list
  - Sorted the list

Uji pengetahuan Anda

1.

Manakah dari panggilan berikut yang membatasi berapa kali variabel lst dilacak pada lima kali?

2.

Apa tujuan dari opsi group?

3.

Misalkan kita membuat referensi dengan kode berikut:

for i in range(10):
    pybryt.Value(foo(i), name="foo", limit=5)
    pybryt.Value(bar(i), group="foo")
    pybryt.Value(baz(i), name="baz")

Berapa banyak anotasi yang ada dalam referensi?