상세 컨텐츠

본문 제목

[Python] 데이터 csv 저장

IT/Simple-Task

by HarimKang 2020. 6. 16. 17:12

본문

Writer: Harim Kang

테스트 출력 결과 csv로 저장하기

Intel korea Validation Team으로 저는 특정 프로젝트에 대한 테스팅 코드를 짜는 업무입니다. Test Code를 실행하고, 테스트 결과를 깔끔하게 csv로 정리하는 작업을 조금 더 간단한 프로젝트로 구성하여 글로 써보았습니다.

목표

  • 미리 작성된 Test Case 파일을 읽어서 Testing을 수행하고 내용과 결과를 csv파일로 정리하여 출력하는 것이 목표입니다.
  • 총 3개의 Test case를 수행하며, 2번은 성공 1번은 실패를 응답하도록 client를 구성하였습니다.

실습 환경

[Test Project Path]
│   test_exec.py
│
├───app
│   └───client.py
│    
│
└───tests
    ├───input
    │       test_case.json
    │
    └───output
  • Test 환경은 위의 구조로 이루어져 있습니다.
  • app/client.py 는 POST, GET, DELETE요청을 응답하는 실습을 위한 간단한 클래스입니다.
  • tests는 input과 output 디렉토리로 이루어져 있는데, input은 테스트 케이스가 담긴 json파일을, output은 테스트 결과를 담을 csv를 저장하는 위치입니다.
  • 현재는 tests/input/test_case.json이 테스트 케이스가 담긴 파일로 존재하고 있으며, output은 test_exec.py를 실행한 결과로 csv파일을 만들어서 저장할 위치입니다.
  • test_exec.py는 test_case.json을 읽어와서 client에게 요청을 하여 명령을 수행하고, 결과를 output에 csv파일로 저장하는 일을 수행합니다.

Test Case

  • Test Case는 총 3개의 Case로 구성하였으며, 각각 POST, GET, DELETE 순서입니다. 각각 tc_id(test case id), name(test case name)를 가지고 있고, commands가 수행해야할 테스트입니다.

Simple Client

  • POST, GET, DELETE에 응답을 하는 간단한 Client를 구성합니다.
  • 응답은 post와 get은 테스트 케이스의 expected_results와 같도록 구성하고, delete에 대해서는 다른 응답을 하도록 구성하였습니다.
class Client:

    def __init__(self):
        pass

    def post(self, resource, data, content_type):
        return {
            "status_code": "201"
        }

    def get(self, resource):
        resp = {
            "status_code": "200",
            "items": [
              {
                "created_at": "string",
                "name": "string",
                "project_id": 2,
                "working_dir": "string"
              }
            ]
        }
        return resp

    def delete(self, resource):
        return {
            "status_code": "404"
        }

테스트 수행 및 결과 출력 (test_exec.py)

import os
import csv
import json
import argparse

from app.client import Client

class TestExecution:

    def __init__(self, csv_file, tc_id, tc_name, commands, expected_results):

        # Constructing an object by receiving parameters
        self.csv_file = csv_file
        self.tc_id = tc_id
        self.tc_name = tc_name
        self.commands = commands
        self.expected_results = expected_results

        self.actual_result = None
        self.status = "NOT TESTED"

    def run(self):
        print('=====Running APP=====')

        # App execution and client creation
        client = Client()

        print('======Testing=====')
        method = self.commands['--method']
        resp = None
        if method == "POST":
            resp = client.post(self.commands['--resource'],
                               self.commands['--representation']['data'],
                               self.commands['--representation']['content-type'])
            self.actual_result = resp['status_code']
        elif method == "GET":
            resp = client.get(self.commands['--resource'])
            self.actual_result = resp
        elif method == "DELETE":
            resp = client.delete(self.commands['--resource'])
            self.actual_result = resp['status_code']

        if resp:
            self.eval_status(resp)

        self.write_output()

    def eval_status(self, resp):
        print('=====Evaluate Status=====')

        # Function that determines status by checking whether status_code matches expected_status
        if resp['status_code'] == self.expected_results['status_code']:
            self.status = 'PASSED'
        else:
            self.status = 'FAILED'

    def write_output(self):
        print('====Write CSV=====')

        data = [
            self.tc_id,
            self.tc_name,
            self.expected_results,
            self.actual_result,
            self.status
        ]

        with open(self.csv_file, 'a', newline='') as _outfile:
            _writer = csv.writer(_outfile)
            _writer.writerow(data)

if __name__ == '__main__':
    # Instance to receive arguments of parser
    parser = argparse.ArgumentParser(description='arguments supported')
    parser.add_argument('-t', '--test_type', default='simple_test', help='input an test type [default : "simple_test"]')
    args = parser.parse_args()
    test_type = args.test_type.strip()

    # Create Output CSV File
    csv_file = './tests/output/' + test_type + '.csv'

    if not os.path.isfile(csv_file):
        header = [
            'TC_ID',
            'TC_Name',
            'Expected_Result',
            'Actual_Result',
            'Status'
        ]

        print('=====Create CSV File & Input CSV File Header...=====')
        with open(csv_file, 'w', newline='') as outfile:
            writer = csv.writer(outfile)
            writer.writerow(header)

    # Open Test Cases file(.json)
    print('=====Test Case Load...=====')
    json_data = json.load(open('./tests/input/test_case.json'))

    for tc in json_data['test_cases']:
        test = TestExecution(csv_file=csv_file,
                             tc_id=tc['tc_id'],
                             tc_name=tc['name'],
                             commands=tc['commands'],
                             expected_results=tc['expected_results'])

        test.run()
  • 테스트 케이스를 가져오는 코드는 아래와 같습니다.

      # Open Test Cases file(.json)
        print('=====Test Case Load...=====')
        json_data = json.load(open('./tests/input/test_case.json'))
  • 아래의 코드는 csv파일 맨 앞 줄에 지정한 변수를 넣는 작업입니다. 각 데이터의 열이 무엇을 의미하는지를 작성합니다.

          # Create Output CSV File
          csv_file = './tests/output/' + test_type + '.csv'
    
          if not os.path.isfile(csv_file):
              header = [
                  'TC_ID',
                  'TC_Name',
                  'Expected_Result',
                  'Actual_Result',
                  'Status'
              ]
    
              print('=====Create CSV File & Input CSV File Header...=====')
              with open(csv_file, 'w', newline='') as outfile:
                  writer = csv.writer(outfile)
                  writer.writerow(header)
  • TestExecution 객체에게 정보를 주고, run을 하면 테스트 수행 후, csv파일이 작성됩니다.

      for tc in json_data['test_cases']:
              test = TestExecution(csv_file=csv_file,
                                   tc_id=tc['tc_id'],
                                   tc_name=tc['name'],
                                   commands=tc['commands'],
                                   expected_results=tc['expected_results'])
    
              test.run()
  • csv파일에 테스트 수행 결과를 작성하는 함수는 write_output() 함수입니다. 클래스의 변수들을 가져와서 파일을 작성합니다.

      def write_output(self):
          print('====Write CSV=====')
    
          data = [
              self.tc_id,
              self.tc_name,
              self.expected_results,
              self.actual_result,
              self.status
          ]
    
          with open(self.csv_file, 'a', newline='') as _outfile:
              _writer = csv.writer(_outfile)
              _writer.writerow(data)

결과

  • output 디렉토리에 csv파일이 작성됩니다. 원하던 대로 2번의 PASS와 1번의 FAIL이 기록되었습니다.

'IT > Simple-Task' 카테고리의 다른 글

[Python] JSON 다루기 기초  (0) 2020.05.22
Docker 설치 및 사용법  (1) 2019.12.31

관련글 더보기

댓글 영역