Industry Insights 20 min read

From Manual Testing to Test Development: Building a Real‑World Test Data Tool

This article traces the evolution of the software testing profession, shares the author’s personal career path from functional testing to test development, and provides a step‑by‑step guide—including architecture, code samples, and deployment—for creating a Python‑based API test data service and a Vue.js web UI to showcase it.

FunTester
FunTester
FunTester
From Manual Testing to Test Development: Building a Real‑World Test Data Tool

Industry Evolution of Testing

Before the rise of the Internet, testing was a simple, mostly manual role with occasional scripting. As internet companies grew, testing diversified into performance, automation, security, and other specialized positions, often organized as distinct departments. The mobile era introduced higher entry barriers, a shift from "software testing" to "QA", and the gradual disappearance of isolated specialist roles in favor of test development.

Personal Career Timeline

2013 – Functional testing

2014 – Performance testing

2014‑2015 – Automation testing

2016‑present – Test development

Performance Testing Phase

In 2013 the author mastered LoadRunner and QTP, then performed a hardware server stress test for a cloud‑disk product. The client demanded hand‑written Java Vuser scripts, exposing the author’s limited Java skills and prompting a shift from tool‑centric work to deeper programming.

Automation Testing Phase

After learning Java, the author transitioned to automation testing. While writing the first hundred test cases, efficiency dropped, leading to the creation of a custom automation framework that managed drivers, utilities, assertions, logging, and reporting. The framework later evolved to include I/O, data generation, network handling, database access, retries, and screenshots.

To synchronize the framework across Android, iOS, H5, and Web projects, Maven was introduced to package the framework as a reusable SDK, decoupling test code from the framework.

Test Development Growth Stages

Learning stage (0→1): Focus on mastering a single domain, such as automation, and building foundational skills.

Exploratory stage (1→N): Rapidly experiment with many ideas, often rebuilding wheels without considering cost or practicality.

Rational stage: Prioritize ROI, solve concrete business and technical problems, and take ownership of improvements.

Note: Developing testing tools is only one aspect of a test developer’s responsibilities.

Client‑Side Tool Development

The author first built a Java Swing tool (around 2014‑2015) to generate test data for both automated and business testing. Later, a graphical wrapper around Android Monkey was created to provide real‑time performance and log visibility, improving usability for non‑technical teammates.

Web‑Based Tool Development

Motivated by the difficulty of distributing compiled client tools, the author migrated the functionality to a web platform using a Java SSH framework for the backend and an Ace Admin template for the frontend. The platform initially served as an internal interface testing management system, later expanding with many experimental features.

Key technology choices:

Backend: Java SSH framework

Frontend: Ace Admin (HTML/CSS/JS) and later iview‑admin Vue.js template

Data generation: Python faker library

API Service Implementation (Python)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from faker import Faker
import json

class TestData(object):
    def __init__(self):
        self.fake = Faker(locale='zh_CN')

    def get_address(self):
        """Generate a random address"""
        return self.fake.address()

    def get_job(self):
        """Generate a random job title"""
        return self.fake.job()

    def get_free_email(self):
        """Generate a random email"""
        return self.fake.free_email()

    def get_phone_number(self):
        """Generate a random phone number"""
        return self.fake.phone_number()

    def get_name_male(self):
        """Generate a random male name"""
        return self.fake.name_male()

Flask routes expose the above methods as JSON APIs (e.g., /example/getaddress, /example/getjob, etc.). Error handling logs exceptions and returns HTTP 500 on failure.

Registering Routes in the Main Application

from .example import exampleviews
app.register_blueprint(exampleviews.demo)

Run the service with python run.py server and access the endpoints via HTTP requests.

Web UI Development (Vue.js + iview‑admin)

A new Vue component get-data.vue displays the generated test data. The component fetches data from the API on mount, shows a loading indicator, and renders fields such as name, phone, email, job, and address.

<template>
  <div>
    <Card title="Test Data" shadow>
      <row :gutter="32">
        <i-col span="24">
          <row type="flex" justify="center"><p>Name: {{ formBody.name }}</p></row>
          <row type="flex" justify="center"><p>Phone: {{ formBody.phone }}</p></row>
          <row type="flex" justify="center"><p>Email: {{ formBody.mail }}</p></row>
          <row type="flex" justify="center"><p>Job: {{ formBody.job }}</p></row>
          <row type="flex" justify="center"><p>Address: {{ formBody.address }}</p></row>
        </i-col>
        <i-col span="24">
          <row type="flex" justify="center">
            <Button size="large" type="primary" @click="getData">Refresh</Button>
          </row>
        </i-col>
      </row>
    </Card>
  </div>
</template>

<script>
import api from '../api/get-data/get-data'
export default {
  name: 'get_data',
  data () { return { formBody: {} } },
  mounted () { this.$Loading.start(); this.getData(); this.$Loading.finish(); },
  methods: {
    getData () {
      api.getprofile('', body => { this.formBody = body.data }, err => {
        if (err.response && [401,403,404].includes(err.response.status)) {
          this.$router.push({ name: String(err.response.status) })
        } else {
          this.$Modal.error({ title: 'Error', content: 'Failed to fetch data', okText: 'OK' })
        }
      })
    }
  }
}
</script>

Supporting API client files ( base.js and get-data.js) configure Axios with environment‑dependent base URLs, request timeouts, and error handling.

Routing Configuration

{
  path: '/data',
  name: 'data',
  component: Main,
  meta: { hideInBread: true },
  children: [{
    path: 'get_data',
    name: 'get_data',
    meta: { icon: '_qq', title: 'Test Data' },
    component: () => import('@/view/get-data.vue')
  }]
},

Localization entries are added to zh-CN.js to display the menu label.

Conclusion

The guide demonstrates how to transform a personal need for test data generation into a reusable API service and a lightweight web UI, illustrating the broader shift in the testing profession from isolated manual tasks to integrated test development and tool engineering.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonSoftware Testingtest automationVue.jstool engineeringAPI development
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.