KaderTarlan

BlogCan

Python Ile Birim Testler

Merhaba uzun süredir uğraştığım test alanı ile ilgili faydalı bilgiler aktarabilmek adına Python ile birim testleri nasıl yazıyoruz ondan bahsedeceğim bu yazımda.

LibreOffice projesinin kaynak koduna Python ile birim testler yazdım. Oraya yazdığım ve kaynak koduna kabul ettirdiğim testlerden birini örnek vererek anlatacağım.

Öncelikle LibreOffice test yazacaksanız yazdığınız kodun en başına bir lisans bildirimi ekliyorsunuz. Yazdığım dosya LibreOffice aittir, belirtilen lisans doğrultusunda yazıyorum gibi.

LibreOffice geliştirdiği Uno modüllerinden testinizde hangilerini kullanacaksanız onları test dosyasına dahil ediyoruz.
from com.sun.star.text import XTextDocument from org.libreoffice.unotest import UnoInProcess

1
2
3
4
5
6
7
8
9
10
11
12
class CheckFlies(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls._uno = UnoInProcess()
        cls._uno.setUp()
        cls.document = cls._uno.openWriterTemplateDoc("CheckFlies.odt")


    @classmethod
    def tearDownClass(cls):
        cls._uno.tearDown()

Python ile yazılan tüm birim testlerimizin class parametresi unittest.TestCase şeklinde olmalı.

Testler için SetUpClass ve tearDownClass sınıf metotlarımız olması gereken metotlardır. SetUpClass metodumuz testler daha başlamadan hazırlanmasını istediğimiz adımları yazdığımız kısımdır. Burada LibreOffice için dökümanları açtığımız, oluşturduğumuz yer de oluyor aynı zamanda. İşlem yapılacak belgemizi öncesinde hazır hale getiriyoruz. tearDownClass metodu ise testler bittikten sonra çalıştırılmasını istediğimiz adımları yazdığımız yerdir. Örneğin açılan dosyamızın kapatılma işlemi burada gerçekleşiyor.

Testlerin başlangıç fonksiyonu “test” deyimi ile başlamalı. Eğer bunu yazmazsak o test aslında hiç çalışmamış olur. Fonksiyonların başına test yazmadığınız zaman çağırmadığınız sürece çalıştırılmayacak fonksiyonlar olur onlar. Ancak “test” yazan her fonksiyonu siz çağırmak zorunda değilsiniz siz testleri çalıştırdığınızda o fonksiyonlarda otomatikmen çağrılırlar. Benim örneğimdeki fonksiyonumuzda “def test_checkFlies(self):” deyimi yer almakta.

Testlerde kullanılan diğer herşey kulandığınız dilin marifetleri ile şekillenecektir. Değindiğim noktalarla iskeleti oluşturduktan sonra Python dilinde yapmak istediğim şeyleri yazdım.

Kullandığım diğer önemli yapı testlerin hepsinde olan Assert adımlarıdır. AssertEqual ile verilen iki parametre arasında eşitliği kontrol edip AssertTrue ile doğruluğunun sağlandığını ölçüp AssertFail ile hata mesajı dönebilirsiniz. Assertion adımları testi test yapan adımlar. Eğer testinizde kontrol adımlarınız yoksa birşeyi test etmiş olmazsınız. Assert çok çeşitlidir, örneğin kullanmanız gereken duruma göre aşağıdakilerden birini seçebilirsiniz:

| ———– | ———– |
| assertEqual(a, b) | a == b |
| assertNotEqual(a, b) | a != b |
| assertTrue(x) | bool(x) is True |
| assertFalse(x) | bool(x) is False |
| assertIs(a, b) | a is b |
| assertIsNot(a, b) | a is not b |
| assertIsNone(x) | x is None |
| assertIsNotNone(x) | x is not None |
| assertIn(a, b) | a in b s |
| assertNotIn(a, b) | a not in b |
| assertIsInstance(a, b) | isinstance(a, b) |
| assertGreater(a, b) | a > b |
| assertGreaterEqual(a, b ) | a >= b |
| assertLess(a, b) | a < b |
| assertLessEqual(a, b) | a <= b |

Bahsini ettiğim testi de paylaşacağım. Testin üzerinden anlattıklarıma tekrar bakarsanız daha kalıcı olacağını düşünüyorum. Kolay gelsin.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'''
  This is file is part of the LibreOffice project.

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

  This file incorporates work covered by the following license notice:

    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements. See the NOTICE file distributed
    with this work for additional information regarding copyright
    ownership. The ASF licenses this file to you under the Apache
    License, Version 2.0 (the "License"); you may not use this file
    except in compliance with the License. You may obtain a copy of
    the License at http://www.apache.org/licenses/LICENSE-2.0 .
'''

from com.sun.star.lang import XMultiServiceFactory
from com.sun.star.text import XTextDocument
from com.sun.star.text import XTextFramesSupplier
from com.sun.star.text import XTextGraphicObjectsSupplier
from com.sun.star.text import XTextEmbeddedObjectsSupplier
from com.sun.star.container import XNameAccess
from com.sun.star.container import NoSuchElementException
from com.sun.star.container import XIndexAccess
from org.libreoffice.unotest import UnoInProcess
import unittest
import unohelper
import os

class CheckFlies(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls._uno = UnoInProcess()
        cls._uno.setUp()
        cls.document = cls._uno.openWriterTemplateDoc("CheckFlies.odt")


    @classmethod
    def tearDownClass(cls):
        cls._uno.tearDown()

    def test_checkFlies(self):
        xTFS = self.__class__.document
        self.checkTextFrames(xTFS)
        xTGOS = self.__class__.document
        self.checkGraphicFrames(xTGOS)
        xTEOS = self.__class__.document
        self.checkEmbeddedFrames(xTEOS)

    def checkEmbeddedFrames(self, xTGOS):
        vExpectedEmbeddedFrames = ["Object1"]
        nEmbeddedFrames = len(vExpectedEmbeddedFrames)
        xEmbeddedFrames = xTGOS.getEmbeddedObjects()
        nCurrentFrameIdx=0

        print (xEmbeddedFrames)
        for sFrameName in xEmbeddedFrames.getElementNames():
            vExpectedEmbeddedFrames.remove(sFrameName)
                # raises ValueError if not found
            print (sFrameName)
            xEmbeddedFrames.getByName(sFrameName)
            self.assertTrue(xEmbeddedFrames.hasByName(sFrameName), "Could not find embedded frame by name.")

        self.assertTrue(not(vExpectedEmbeddedFrames), "Missing expected embedded frames.")

        xEmbeddedFramesIdx = xEmbeddedFrames

        self.assertEqual(nEmbeddedFrames, xEmbeddedFramesIdx.getCount()) #Unexpected number of embedded frames reported

        for nCurrentFrameIdx in range(xEmbeddedFramesIdx.getCount()):
            xEmbeddedFramesIdx.getByIndex(nCurrentFrameIdx)

    def checkGraphicFrames(self, xTGOS):
        vExpectedGraphicFrames = ["graphics1"]
        nGraphicFrames = len(vExpectedGraphicFrames)
        xGraphicFrames = xTGOS.getGraphicObjects()
        nCurrentFrameIdx = 0
        for sFrameName in xGraphicFrames.getElementNames():
            vExpectedGraphicFrames.remove(sFrameName)
                # raises ValueError if not found
            xGraphicFrames.getByName(sFrameName)
            self.assertTrue(
                xGraphicFrames.hasByName(sFrameName),
                "Could not find graphics frame by name.")
        self.assertTrue(
            not(vExpectedGraphicFrames),
            "Missing expected graphics frames.")

        xGraphicFramesIdx = xGraphicFrames
        self.assertEqual(nGraphicFrames,xGraphicFramesIdx.getCount()) #Unexpected number of graphics frames reported

        for nCurrentFrameIdx in range(xGraphicFramesIdx.getCount()):
            xGraphicFramesIdx.getByIndex(nCurrentFrameIdx);

    def checkTextFrames(self, xTFS):
        vExpectedTextFrames= ["Frame1" , "Frame2"]
        nTextFrames = len(vExpectedTextFrames)
        xTextFrames = xTFS.getTextFrames()
        nCurrentFrameIdx=0

        for sFrameName in xTextFrames.getElementNames():
            vExpectedTextFrames.remove(sFrameName)
                # raises ValueError if not found
            xTextFrames.getByName(sFrameName)
            self.assertTrue(
                xTextFrames.hasByName(sFrameName),
                "Could not find text frame by name.")

        self.assertTrue(
            not(vExpectedTextFrames), "Missing expected text frames.")

        xTextFramesIdx = xTextFrames

        self.assertEqual(nTextFrames, xTextFrames.getCount()) #Unexpected number of text frames reported

        for nCurrentFrameIdx in range(xTextFramesIdx.getCount()):
            xTextFramesIdx.getByIndex(nCurrentFrameIdx)

if __name__ == "__main__":
    unittest.main()